diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a8ab16a --- /dev/null +++ b/.clang-format @@ -0,0 +1,111 @@ +# +# Clang formatting rules: https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# The clang-format npm package (https://github.com/angular/clang-format) uses +# a pre-built clang-format.exe from http://llvm.org/builds/ +# +--- +# We use defaults from the Microsoft style +BasedOnStyle: Microsoft +--- +Language: Cpp + +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakAfterJavaFieldAnnotations: false +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces : true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +FixNamespaceComments: true +ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, TEST_CLASS, TEST_CLASS_EX ] +IncludeBlocks: Preserve +IncludeCategories: + - Regex: 'pch.h' + Priority: -1 + - Regex: '.*\.g\..*' + Priority: 1 + - Regex: '^<.*\.h(pp)?>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 + - Regex: '.*' + Priority: 4 +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +TabWidth: 2 +UseTab: Never +... diff --git a/change/@microsoft-mso-2020-04-01-07-47-10-Clang-format2.json b/change/@microsoft-mso-2020-04-01-07-47-10-Clang-format2.json new file mode 100644 index 0000000..747a125 --- /dev/null +++ b/change/@microsoft-mso-2020-04-01-07-47-10-Clang-format2.json @@ -0,0 +1,8 @@ +{ + "type": "patch", + "comment": "Formatted code with ClangFormat", + "packageName": "@microsoft/mso", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-01T14:47:10.009Z" +} \ No newline at end of file diff --git a/libs/comUtil/include/comUtil/qiCast.h b/libs/comUtil/include/comUtil/qiCast.h index 99baa30..0897991 100644 --- a/libs/comUtil/include/comUtil/qiCast.h +++ b/libs/comUtil/include/comUtil/qiCast.h @@ -14,53 +14,59 @@ #include #include -namespace Mso { -namespace ComUtil { +namespace Mso { namespace ComUtil { -template -HRESULT HrCoCreateInstance(Mso::TCntPtr& target, REFCLSID rclsid, _In_opt_ LPUNKNOWN pUnkOuter = nullptr, DWORD dwClsContext = CLSCTX_ALL) noexcept +template +HRESULT HrCoCreateInstance( + Mso::TCntPtr& target, + REFCLSID rclsid, + _In_opt_ LPUNKNOWN pUnkOuter = nullptr, + DWORD dwClsContext = CLSCTX_ALL) noexcept { - return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), reinterpret_cast(target.GetAddressOf())); + return ::CoCreateInstance( + rclsid, pUnkOuter, dwClsContext, __uuidof(T), reinterpret_cast(target.GetAddressOf())); } #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -template -HRESULT HrCoCreateInstance(Mso::TCntPtr& target, _In_z_ LPCOLESTR szProgID, _In_opt_ LPUNKNOWN pUnkOuter = nullptr, DWORD dwClsContext = CLSCTX_ALL) noexcept +template +HRESULT HrCoCreateInstance( + Mso::TCntPtr& target, + _In_z_ LPCOLESTR szProgID, + _In_opt_ LPUNKNOWN pUnkOuter = nullptr, + DWORD dwClsContext = CLSCTX_ALL) noexcept { - CLSID clsid; - HRESULT hr = ::CLSIDFromProgID(szProgID, &clsid); - return SUCCEEDED(hr) ? HrCoCreateInstance(target, clsid, pUnkOuter, dwClsContext) : hr; + CLSID clsid; + HRESULT hr = ::CLSIDFromProgID(szProgID, &clsid); + return SUCCEEDED(hr) ? HrCoCreateInstance(target, clsid, pUnkOuter, dwClsContext) : hr; } #endif -} // ComUtil -} // Mso +}} // namespace Mso::ComUtil namespace Mso { template -__declspec(deprecated("Use Mso::ComUtil::AreEqualObjects")) bool AreEqualObjects(const T1* pLeft, const T2* pRight) noexcept +__declspec( + deprecated("Use Mso::ComUtil::AreEqualObjects")) bool AreEqualObjects(const T1* pLeft, const T2* pRight) noexcept { - return Mso::ComUtil::AreEqualObjects(pLeft, pRight); + return Mso::ComUtil::AreEqualObjects(pLeft, pRight); } -} // Mso +} // namespace Mso #endif // MS_TARGET_WINDOWS -namespace Mso { -namespace Details { +namespace Mso { namespace Details { // Overloaded global function to provide to IID_PPV_ARGS that support Details::TCntPtrRef template void** IID_PPV_ARGS_Helper(_Inout_ TCntPtrRef pp) noexcept { - static_assert(std::is_base_of::value, "T has to derive from IUnknown"); - return pp; + static_assert(std::is_base_of::value, "T has to derive from IUnknown"); + return pp; } -} // Details -} // Mso +}} // namespace Mso::Details #endif // __cplusplus #endif // LIBLET_COMUTIL_QICAST_H diff --git a/libs/comUtil/include/comUtil/qiCastCore.h b/libs/comUtil/include/comUtil/qiCastCore.h index 9fbbab3..0450963 100644 --- a/libs/comUtil/include/comUtil/qiCastCore.h +++ b/libs/comUtil/include/comUtil/qiCastCore.h @@ -30,188 +30,199 @@ //============================================================================ /** - qi_cast(source, optional riid) + qi_cast(source, optional riid) - Primary version of the template. Generally speaking, it is preferable to - add a MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") declaration to the class/interface, or use - MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") if type is already defined. Otherwise it can be - explicitly passed as a 2nd parameter. + Primary version of the template. Generally speaking, it is preferable to + add a MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") declaration to the class/interface, or use + MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") if type is already defined. Otherwise it can be + explicitly passed as a 2nd parameter. */ -template< typename TTarget, typename TSource > -Mso::TCntPtr< TTarget > qi_cast( TSource& piSource, const IID &riid = __uuidof( TTarget ) ) noexcept +template +Mso::TCntPtr qi_cast(TSource& piSource, const IID& riid = __uuidof(TTarget)) noexcept { - Mso::TCntPtr< TTarget > spTarget; - if( piSource != nullptr ) - { - if( FAILED ( piSource->QueryInterface( riid, &spTarget ) ) ) - spTarget.Empty(); - } - return spTarget; + Mso::TCntPtr spTarget; + if (piSource != nullptr) + { + if (FAILED(piSource->QueryInterface(riid, &spTarget))) + spTarget.Empty(); + } + return spTarget; } /** - qi_cast(const source, optional riid) + qi_cast(const source, optional riid) - Shorthand for classes and interfaces with an MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") attribute - or a MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") assignment. - TSource does not include the pointer type, which allows the compiler - to disambiguate against the primary function. + Shorthand for classes and interfaces with an MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") attribute + or a MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") assignment. + TSource does not include the pointer type, which allows the compiler + to disambiguate against the primary function. */ -template< typename TTarget, typename TSource > -Mso::TCntPtr< TTarget > qi_cast( const TSource *piSource, const IID &riid = __uuidof( TTarget ) ) noexcept +template +Mso::TCntPtr qi_cast(const TSource* piSource, const IID& riid = __uuidof(TTarget)) noexcept { - TSource *piSourceNonConst = const_cast< TSource* >( piSource ); - return qi_cast< TTarget, TSource* >( piSourceNonConst, riid ); + TSource* piSourceNonConst = const_cast(piSource); + return qi_cast(piSourceNonConst, riid); } #pragma warning(push) -#pragma warning(disable:4995) // VerifyElseCrashSz gives "warning C4995: 'IsDebuggerPresent': name was marked as #pragma deprecated" +#pragma warning(disable : 4995) // VerifyElseCrashSz gives "warning C4995: 'IsDebuggerPresent': name was marked as + // #pragma deprecated" /** - qi_cast_or_crash(source, optional riid) + qi_cast_or_crash(source, optional riid) - Calls qi_cast and crashes if it fails. - This is useful when the qi_cast must succeed or otherwise it is a bug. + Calls qi_cast and crashes if it fails. + This is useful when the qi_cast must succeed or otherwise it is a bug. */ -template< typename TTarget, typename TSource > -Mso::TCntPtr< TTarget > qi_cast_or_crash( TSource& piSource, const IID &riid = __uuidof( TTarget ) ) noexcept +template +Mso::TCntPtr qi_cast_or_crash(TSource& piSource, const IID& riid = __uuidof(TTarget)) noexcept { - Mso::TCntPtr< TTarget > target = qi_cast< TTarget >( piSource, riid ); - VerifyElseCrashSzTag( target, "Query interface failed." , 0x022054c3 /* tag_ciftd */); - return target; + Mso::TCntPtr target = qi_cast(piSource, riid); + VerifyElseCrashSzTag(target, "Query interface failed.", 0x022054c3 /* tag_ciftd */); + return target; } /** - qi_cast_or_crash(const source, optional riid) + qi_cast_or_crash(const source, optional riid) - Calls qi_cast and crashes if it fails. - This is useful when the qi_cast must succeed or otherwise it is a bug. + Calls qi_cast and crashes if it fails. + This is useful when the qi_cast must succeed or otherwise it is a bug. */ -template< typename TTarget, typename TSource > -Mso::TCntPtr< TTarget > qi_cast_or_crash( const TSource *piSource, const IID &riid = __uuidof( TTarget ) ) noexcept +template +Mso::TCntPtr qi_cast_or_crash(const TSource* piSource, const IID& riid = __uuidof(TTarget)) noexcept { - Mso::TCntPtr< TTarget > target = qi_cast< TTarget >( piSource, riid ); - VerifyElseCrashSzTag( target, "Query interface failed." , 0x022054c4 /* tag_cifte */); - return target; + Mso::TCntPtr target = qi_cast(piSource, riid); + VerifyElseCrashSzTag(target, "Query interface failed.", 0x022054c4 /* tag_cifte */); + return target; } #pragma warning(pop) /** - simpleqi_cast(source, optional riid) + simpleqi_cast(source, optional riid) - Primary version of the template. Generally speaking, it is preferable to - add a MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") declaration to the class/interface, or use - MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") if type is already defined. Otherwise it can be - explicitly passed as a 2nd parameter. + Primary version of the template. Generally speaking, it is preferable to + add a MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") declaration to the class/interface, or use + MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") if type is already defined. Otherwise it can be + explicitly passed as a 2nd parameter. - Used for Simple interfaces that do not AddRef + Used for Simple interfaces that do not AddRef */ -template< typename TTarget, typename TSource > -TTarget* simpleqi_cast( TSource& piSource, const IID &riid = __uuidof( TTarget ) ) noexcept +template +TTarget* simpleqi_cast(TSource& piSource, const IID& riid = __uuidof(TTarget)) noexcept { - TTarget* pTarget = nullptr; - if( piSource != nullptr ) - { - if( FAILED( piSource->QueryInterface( riid, reinterpret_cast< void** >( &pTarget ) ) ) ) - pTarget = nullptr; - } - return pTarget; + TTarget* pTarget = nullptr; + if (piSource != nullptr) + { + if (FAILED(piSource->QueryInterface(riid, reinterpret_cast(&pTarget)))) + pTarget = nullptr; + } + return pTarget; } /** - simpleqi_cast(const source, optional riid) + simpleqi_cast(const source, optional riid) - Shorthand for classes and interfaces with an MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") attribute - or a MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") assignment. - TSource does not include the pointer type, which allows the compiler - to disambiguate against the primary function. + Shorthand for classes and interfaces with an MSO_CLASS_GUID(T, "") / MSO_STRUCT_GUID(T, "") attribute + or a MSO_ASSIGN_CLASS_GUID(T, "") / MSO_ASSIGN_STRUCT_GUID(T, "") assignment. + TSource does not include the pointer type, which allows the compiler + to disambiguate against the primary function. */ -template< typename TTarget, typename TSource > -TTarget* simpleqi_cast( const TSource *piSource, const IID &riid = __uuidof( TTarget ) ) noexcept +template +TTarget* simpleqi_cast(const TSource* piSource, const IID& riid = __uuidof(TTarget)) noexcept { - TSource *piSourceNonConst = const_cast< TSource* >( piSource ); - return simpleqi_cast< TTarget, TSource *>( piSourceNonConst, riid ); + TSource* piSourceNonConst = const_cast(piSource); + return simpleqi_cast(piSourceNonConst, riid); } -namespace Mso { -namespace ComUtil { +namespace Mso { namespace ComUtil { template -HRESULT HrQueryFrom(Mso::TCntPtr& target, const TOther* pOther, const IID &riid = __uuidof(T)) noexcept +HRESULT HrQueryFrom(Mso::TCntPtr& target, const TOther* pOther, const IID& riid = __uuidof(T)) noexcept { - if (pOther == nullptr) - return E_POINTER; - return const_cast(pOther)->QueryInterface(riid, reinterpret_cast(target.ClearAndGetAddressOf())); -} - -template -HRESULT HrQueryFrom(Mso::TCntPtr& target, const TOther& other, const IID &riid = __uuidof(T)) noexcept -{ - if (other == nullptr) - return E_POINTER; - return const_cast(other)->QueryInterface(riid, reinterpret_cast(target.ClearAndGetAddressOf())); + if (pOther == nullptr) + return E_POINTER; + return const_cast(pOther)->QueryInterface(riid, reinterpret_cast(target.ClearAndGetAddressOf())); } template -HRESULT HrQueryFrom(Mso::TCntPtr& target, const Mso::TCntPtr& other, const IID &riid = __uuidof(T)) noexcept +HRESULT HrQueryFrom(Mso::TCntPtr& target, const TOther& other, const IID& riid = __uuidof(T)) noexcept { - if (other == nullptr) - return E_POINTER; - return const_cast&>(other)->QueryInterface(riid, reinterpret_cast(target.ClearAndGetAddressOf())); + if (other == nullptr) + return E_POINTER; + return const_cast(other)->QueryInterface(riid, reinterpret_cast(target.ClearAndGetAddressOf())); } template -bool FQueryFrom(Mso::TCntPtr& target, const TOther* pOther, const IID &riid = __uuidof(T)) noexcept +HRESULT HrQueryFrom(Mso::TCntPtr& target, const Mso::TCntPtr& other, const IID& riid = __uuidof(T)) noexcept { - return SUCCEEDED(HrQueryFrom(target, pOther, riid)); + if (other == nullptr) + return E_POINTER; + return const_cast&>(other)->QueryInterface( + riid, reinterpret_cast(target.ClearAndGetAddressOf())); } template -bool FQueryFrom(Mso::TCntPtr& target, const TOther& other, const IID &riid = __uuidof(T)) noexcept +bool FQueryFrom(Mso::TCntPtr& target, const TOther* pOther, const IID& riid = __uuidof(T)) noexcept { - return SUCCEEDED(HrQueryFrom(target, other, riid)); + return SUCCEEDED(HrQueryFrom(target, pOther, riid)); } -template -bool FQueryFrom(Mso::TCntPtr& target, const Mso::TCntPtr& other, const IID &riid = __uuidof(T)) noexcept +template +bool FQueryFrom(Mso::TCntPtr& target, const TOther& other, const IID& riid = __uuidof(T)) noexcept { - return SUCCEEDED(HrQueryFrom(target, other, riid)); + return SUCCEEDED(HrQueryFrom(target, other, riid)); +} + +template +bool FQueryFrom(Mso::TCntPtr& target, const Mso::TCntPtr& other, const IID& riid = __uuidof(T)) noexcept +{ + return SUCCEEDED(HrQueryFrom(target, other, riid)); } /// Checks if two IUnknown objects are equal. template bool AreEqualObjects(const T1* pLeft, const T2* pRight) noexcept { - if (reinterpret_cast(pLeft) == reinterpret_cast(pRight)) - return true; // Both pointers are the same - if (pLeft == nullptr || pRight == nullptr) - return false; // One is null the other is not + if (reinterpret_cast(pLeft) == reinterpret_cast(pRight)) + return true; // Both pointers are the same + if (pLeft == nullptr || pRight == nullptr) + return false; // One is null the other is not - // Compare IUnknown pointers. - auto punk1 = qi_cast(pLeft); - if (!punk1) - return false; + // Compare IUnknown pointers. + auto punk1 = qi_cast(pLeft); + if (!punk1) + return false; - auto punk2 = qi_cast(pRight); - if (!punk2) - return false; + auto punk2 = qi_cast(pRight); + if (!punk2) + return false; - IUnknown* pComp1 = Details::TCntPtrAddRefStrategyImpl::TAddRefStrategy::Strategy>::GetIUnknownForObjectCompare(punk1.Get()); - IUnknown* pComp2 = Details::TCntPtrAddRefStrategyImpl::TAddRefStrategy::Strategy>::GetIUnknownForObjectCompare(punk2.Get()); - return (pComp1 == pComp2); + IUnknown* pComp1 = Details::TCntPtrAddRefStrategyImpl< + Details::AddRefStrategyForType::TAddRefStrategy::Strategy>::GetIUnknownForObjectCompare(punk1.Get()); + IUnknown* pComp2 = Details::TCntPtrAddRefStrategyImpl< + Details::AddRefStrategyForType::TAddRefStrategy::Strategy>::GetIUnknownForObjectCompare(punk2.Get()); + return (pComp1 == pComp2); } template -bool AreEqualObjects(const T1* pLeft, const Mso::TCntPtr& right) noexcept { return Mso::ComUtil::AreEqualObjects(pLeft, right.Get()); } +bool AreEqualObjects(const T1* pLeft, const Mso::TCntPtr& right) noexcept +{ + return Mso::ComUtil::AreEqualObjects(pLeft, right.Get()); +} template -bool AreEqualObjects(const Mso::TCntPtr& left, const T2* pRight) noexcept { return Mso::ComUtil::AreEqualObjects(left.Get(), pRight); } +bool AreEqualObjects(const Mso::TCntPtr& left, const T2* pRight) noexcept +{ + return Mso::ComUtil::AreEqualObjects(left.Get(), pRight); +} template -bool AreEqualObjects(const Mso::TCntPtr& left, const Mso::TCntPtr& right) noexcept { return Mso::ComUtil::AreEqualObjects(left.Get(), right.Get()); } +bool AreEqualObjects(const Mso::TCntPtr& left, const Mso::TCntPtr& right) noexcept +{ + return Mso::ComUtil::AreEqualObjects(left.Get(), right.Get()); +} -} // ComUtil -} // Mso +}} // namespace Mso::ComUtil #endif // LIBLET_COMUTIL_QICASTCORE_H diff --git a/libs/compilerAdapters/include/compilerAdapters/compilerFeatures.h b/libs/compilerAdapters/include/compilerAdapters/compilerFeatures.h index bd20db2..dd32fbc 100644 --- a/libs/compilerAdapters/include/compilerAdapters/compilerFeatures.h +++ b/libs/compilerAdapters/include/compilerAdapters/compilerFeatures.h @@ -11,23 +11,22 @@ // Check if Microsoft's Structured Exception Handling (SEH) are supported. #ifndef MSO_HAS_SEH -# if defined(_MSC_VER) || defined(__BORLANDC__) -# define MSO_HAS_SEH 1 -# else -# define MSO_HAS_SEH 0 -# endif +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define MSO_HAS_SEH 1 +#else +#define MSO_HAS_SEH 0 +#endif #endif // MSO_HAS_SEH - // Check if compiler supports UUID #ifndef COMPILER_SUPPORTS_UUID -# if defined(__clang__) || defined(__GNUC__) -# define COMPILER_SUPPORTS_UUID 0 -# elif defined(_MSC_VER) -# define COMPILER_SUPPORTS_UUID 1 -# else -# error Unsupported compiler type. -# endif +#if defined(__clang__) || defined(__GNUC__) +#define COMPILER_SUPPORTS_UUID 0 +#elif defined(_MSC_VER) +#define COMPILER_SUPPORTS_UUID 1 +#else +#error Unsupported compiler type. +#endif #endif #endif // COMPILERADAPTERS_COMPILERFEATURES_H diff --git a/libs/compilerAdapters/include/compilerAdapters/compilerWarnings.h b/libs/compilerAdapters/include/compilerAdapters/compilerWarnings.h index 103845b..a938d34 100644 --- a/libs/compilerAdapters/include/compilerAdapters/compilerWarnings.h +++ b/libs/compilerAdapters/include/compilerAdapters/compilerWarnings.h @@ -2,15 +2,15 @@ // Licensed under the MIT license. /** - This header contains cross-plat macros for suppressing compiler warnings - - Alphabetically add a [BEGIN|END]_DISABLE_WARNING_* pair of macros for the compiler warning. - - clang-only: use BEGIN_DISABLE_COMPILER_WARNING_CLANG with the -W argument - msvc-only: use BEGIN_DISABLE_COMPILER_WARNING_MSVC with the warning number - both: use BEGIN_DISABLE_COMPILER_WARNING with both values - - FUTURE: auto-generate this from shared file + This header contains cross-plat macros for suppressing compiler warnings + + Alphabetically add a [BEGIN|END]_DISABLE_WARNING_* pair of macros for the compiler warning. + + clang-only: use BEGIN_DISABLE_COMPILER_WARNING_CLANG with the -W argument + msvc-only: use BEGIN_DISABLE_COMPILER_WARNING_MSVC with the warning number + both: use BEGIN_DISABLE_COMPILER_WARNING with both values + + FUTURE: auto-generate this from shared file */ #ifndef LIBLET_COMPILERADAPTERS_COMPILERWARNINGS_H #define LIBLET_COMPILERADAPTERS_COMPILERWARNINGS_H @@ -25,7 +25,8 @@ #define BEGIN_DISABLE_WARNING_HEADER_HYGIENE_VARIABLE() BEGIN_DISABLE_COMPILER_WARNING_CLANG("-Wheader-hygiene") #define END_DISABLE_WARNING_HEADER_HYGIENE_VARIABLE() END_DISABLE_COMPILER_WARNING() -#define BEGIN_DISABLE_WARNING_INCONSISTENT_MISSING_OVERRIDE() BEGIN_DISABLE_COMPILER_WARNING_CLANG("-Winconsistent-missing-override") +#define BEGIN_DISABLE_WARNING_INCONSISTENT_MISSING_OVERRIDE() \ + BEGIN_DISABLE_COMPILER_WARNING_CLANG("-Winconsistent-missing-override") #define END_DISABLE_WARNING_INCONSISTENT_MISSING_OVERRIDE() END_DISABLE_COMPILER_WARNING() #define BEGIN_DISABLE_WARNING_UNUSED_CONST_VARIABLE() BEGIN_DISABLE_COMPILER_WARNING_CLANG("-Wunused-const-variable") diff --git a/libs/compilerAdapters/include/compilerAdapters/compilerWarnings_impl.h b/libs/compilerAdapters/include/compilerAdapters/compilerWarnings_impl.h index df41fea..49750b2 100644 --- a/libs/compilerAdapters/include/compilerAdapters/compilerWarnings_impl.h +++ b/libs/compilerAdapters/include/compilerAdapters/compilerWarnings_impl.h @@ -2,8 +2,8 @@ // Licensed under the MIT license. /** - Implementation details for suppressing compiler warnings in a cross-plat manner. - */ + Implementation details for suppressing compiler warnings in a cross-plat manner. + */ #ifndef LIBLET_COMPILERADAPTERS_COMPILERWARNINGS_IMPL_H #define LIBLET_COMPILERADAPTERS_COMPILERWARNINGS_IMPL_H @@ -16,9 +16,9 @@ #define COMPILER_WARNING_POP() __pragma(clang diagnostic pop) // See https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html -#elif defined (__GNUC__) +#elif defined(__GNUC__) -//TODO: Implement GCC-specific warnings. +// TODO: Implement GCC-specific warnings. #define COMPILER_WARNING_PUSH() #define COMPILER_WARNING_DISABLE_ALL(msvcNum, gccWarn) #define COMPILER_WARNING_DISABLE_MSVC(msvcNum) @@ -29,23 +29,23 @@ #define COMPILER_WARNING_PUSH() __pragma(warning(push)) #define COMPILER_WARNING_DISABLE_ALL(msvcNum, clangWarn) COMPILER_WARNING_DISABLE_MSVC(msvcNum) -#define COMPILER_WARNING_DISABLE_MSVC(msvcNum) __pragma(warning(disable:##msvcNum)) +#define COMPILER_WARNING_DISABLE_MSVC(msvcNum) __pragma(warning(disable :##msvcNum)) #define COMPILER_WARNING_DISABLE_CLANG(clangWarn) #define COMPILER_WARNING_POP() __pragma(warning(pop)) #endif #define BEGIN_DISABLE_COMPILER_WARNING_ALL(msvcNum, clangWarn) \ - COMPILER_WARNING_PUSH() \ - COMPILER_WARNING_DISABLE_ALL(msvcNum, clangWarn) \ + COMPILER_WARNING_PUSH() \ + COMPILER_WARNING_DISABLE_ALL(msvcNum, clangWarn) #define BEGIN_DISABLE_COMPILER_WARNING_MSVC(msvcNum) \ - COMPILER_WARNING_PUSH() \ - COMPILER_WARNING_DISABLE_MSVC(msvcNum) \ + COMPILER_WARNING_PUSH() \ + COMPILER_WARNING_DISABLE_MSVC(msvcNum) #define BEGIN_DISABLE_COMPILER_WARNING_CLANG(clangWarn) \ - COMPILER_WARNING_PUSH() \ - COMPILER_WARNING_DISABLE_CLANG(clangWarn) \ + COMPILER_WARNING_PUSH() \ + COMPILER_WARNING_DISABLE_CLANG(clangWarn) #define END_DISABLE_COMPILER_WARNING() COMPILER_WARNING_POP() diff --git a/libs/compilerAdapters/include/compilerAdapters/cppMacros.h b/libs/compilerAdapters/include/compilerAdapters/cppMacros.h index a307f39..52b4694 100644 --- a/libs/compilerAdapters/include/compilerAdapters/cppMacros.h +++ b/libs/compilerAdapters/include/compilerAdapters/cppMacros.h @@ -2,21 +2,21 @@ // Licensed under the MIT license. /** - Various low level macros that are globally useful + Various low level macros that are globally useful */ #pragma once #ifndef COMPILERADAPTERS_CPPMACROS_H #define COMPILERADAPTERS_CPPMACROS_H /** - Broadly used macros + Broadly used macros */ #ifndef FImplies -#define FImplies(a, b) (!(a) || (b)) +#define FImplies(a, b) (!(a) || (b)) #endif #ifndef FBiImplies -#define FBiImplies(a, b) (!(a) == !(b)) +#define FBiImplies(a, b) (!(a) == !(b)) #endif #ifndef RgC @@ -24,75 +24,94 @@ #endif /** - Statement - used for control flow macros like Check, IfFailGo - Make the macro act like a statement. + Statement - used for control flow macros like Check, IfFailGo + Make the macro act like a statement. */ #ifndef __GNUC__ -#define Statement(x) __pragma(warning(push)) __pragma(warning(disable:4127 25037)) do { x; } while(0) __pragma(warning(pop)) +#define Statement(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4127 25037)) do \ + { \ + x; \ + } \ + while (0) \ + __pragma(warning(pop)) #else -#define Statement(x) do { x; } while(0) -// error: there are no arguments to '__noop' that depend on a template parameter, so a declaration of '__noop' must be available [-fpermissive] +#define Statement(x) \ + do \ + { \ + x; \ + } while (0) +// error: there are no arguments to '__noop' that depend on a template parameter, so a declaration of '__noop' must be +// available [-fpermissive] #define __noop() #endif /** - Prevent the compiler from automatically providing implementations of various - class features. Use the macro in your class public: section. - TODO: probably need to update with new Move functions + Prevent the compiler from automatically providing implementations of various + class features. Use the macro in your class public: section. + TODO: probably need to update with new Move functions */ #ifndef __GNUC__ -#define MSO_NO_COPYCONSTR( C ) __pragma(warning(suppress:4822)) C(const C&) = delete -#define MSO_NO_ASSIGNMENT( C ) __pragma(warning(suppress:4822)) const C& operator=(const C&) = delete -#define MSO_NO_DEFAULTCONSTR( C ) __pragma(warning(suppress:4822)) explicit C() = delete +#define MSO_NO_COPYCONSTR(C) __pragma(warning(suppress : 4822)) C(const C &) = delete +#define MSO_NO_ASSIGNMENT(C) __pragma(warning(suppress : 4822)) const C &operator=(const C &) = delete +#define MSO_NO_DEFAULTCONSTR(C) __pragma(warning(suppress : 4822)) explicit C() = delete #else -#define MSO_NO_COPYCONSTR( C ) C(const C&) = delete -#define MSO_NO_ASSIGNMENT( C ) const C& operator=(const C&) = delete -#define MSO_NO_DEFAULTCONSTR( C ) explicit C() = delete +#define MSO_NO_COPYCONSTR(C) C(const C &) = delete +#define MSO_NO_ASSIGNMENT(C) const C &operator=(const C &) = delete +#define MSO_NO_DEFAULTCONSTR(C) explicit C() = delete #endif #ifndef DECLARE_COPYCONSTR_AND_ASSIGNMENT -#define DECLARE_COPYCONSTR_AND_ASSIGNMENT( C ) MSO_NO_COPYCONSTR( C ); MSO_NO_ASSIGNMENT( C ) +#define DECLARE_COPYCONSTR_AND_ASSIGNMENT(C) \ + MSO_NO_COPYCONSTR(C); \ + MSO_NO_ASSIGNMENT(C) #endif #if defined(__cplusplus) #include /** - When using an enum class to define a set of bitflags, normal bitflag - enum operations, such as |, ^, and &, don't work without lots of casts. - Use this macro to define |, ^, and & for your enum class, where |, ^ and ~ - will return an enum class type, and & will evaluate to true or false. - The implementation causes error C3281 (global operator cannot have - managed type in signature) for managed code. + When using an enum class to define a set of bitflags, normal bitflag + enum operations, such as |, ^, and &, don't work without lots of casts. + Use this macro to define |, ^, and & for your enum class, where |, ^ and ~ + will return an enum class type, and & will evaluate to true or false. + The implementation causes error C3281 (global operator cannot have + managed type in signature) for managed code. */ -#define ENUM_CLASS_FLAGS_OPERATORS(TEnum) \ - constexpr TEnum operator~(TEnum a) noexcept \ - { \ - return static_cast(~static_cast::type>(a)); \ - } \ - constexpr TEnum operator|(TEnum a, TEnum b) noexcept \ - { \ - return static_cast(static_cast::type>(a) | static_cast::type>(b)); \ - } \ - constexpr bool operator&(TEnum a, TEnum b) noexcept \ - { \ - return !!(static_cast::type>(a) & static_cast::type>(b)); \ - } \ - constexpr TEnum operator^(TEnum a, TEnum b) noexcept \ - { \ - return static_cast(static_cast::type>(a) ^ static_cast::type>(b)); \ - } \ - inline TEnum& operator|=(TEnum& a, TEnum b) noexcept \ - { \ - return reinterpret_cast(reinterpret_cast::type&>(a) |= static_cast::type>(b)); \ - } \ - inline TEnum& operator&=(TEnum& a, TEnum b) noexcept \ - { \ - return reinterpret_cast(reinterpret_cast::type&>(a) &= static_cast::type>(b)); \ - } \ - inline TEnum& operator^=(TEnum& a, TEnum b) noexcept \ - { \ - return reinterpret_cast(reinterpret_cast::type&>(a) ^= static_cast::type>(b)); \ - } +#define ENUM_CLASS_FLAGS_OPERATORS(TEnum) \ + constexpr TEnum operator~(TEnum a) noexcept \ + { \ + return static_cast(~static_cast::type>(a)); \ + } \ + constexpr TEnum operator|(TEnum a, TEnum b) noexcept \ + { \ + return static_cast(static_cast::type>(a) | \ + static_cast::type>(b)); \ + } \ + constexpr bool operator&(TEnum a, TEnum b) noexcept \ + { \ + return !!(static_cast::type>(a) & \ + static_cast::type>(b)); \ + } \ + constexpr TEnum operator^(TEnum a, TEnum b) noexcept \ + { \ + return static_cast(static_cast::type>(a) ^ \ + static_cast::type>(b)); \ + } \ + inline TEnum &operator|=(TEnum &a, TEnum b) noexcept \ + { \ + return reinterpret_cast(reinterpret_cast::type &>(a) |= \ + static_cast::type>(b)); \ + } \ + inline TEnum &operator&=(TEnum &a, TEnum b) noexcept \ + { \ + return reinterpret_cast(reinterpret_cast::type &>(a) &= \ + static_cast::type>(b)); \ + } \ + inline TEnum &operator^=(TEnum &a, TEnum b) noexcept \ + { \ + return reinterpret_cast(reinterpret_cast::type &>(a) ^= \ + static_cast::type>(b)); \ + } #else // !__cplusplus @@ -101,9 +120,9 @@ #endif // !__cplusplus /** - Macros to help share enums between C++ and CX. - Enums must derive from int (the default) - Flag enums must derive from unsigned int + Macros to help share enums between C++ and CX. + Enums must derive from int (the default) + Flag enums must derive from unsigned int */ #if defined(_WINRT_COMP) && !defined(__clang__) #define EXPOSE_WINRT_ENUM public @@ -114,9 +133,9 @@ #endif /** - Macros to force placement of symbols into a particular segment. - For example on iOS ensure large globals aren't placed in the text - segment because there is a size limit enforced by Apple. + Macros to force placement of symbols into a particular segment. + For example on iOS ensure large globals aren't placed in the text + segment because there is a size limit enforced by Apple. */ #if MS_TARGET_APPLE #define DATA_SEGMENT_CONST __attribute__((section("__DATA,__const"))) @@ -125,7 +144,7 @@ #endif #if __GNUC__ -#define __forceinline __attribute__ ((always_inline, unused)) +#define __forceinline __attribute__((always_inline, unused)) // Stub __declspec in GCC #define __declspec(s) #endif diff --git a/libs/compilerAdapters/include/compilerAdapters/cppMacrosDebug.h b/libs/compilerAdapters/include/compilerAdapters/cppMacrosDebug.h index 4785246..1772b44 100644 --- a/libs/compilerAdapters/include/compilerAdapters/cppMacrosDebug.h +++ b/libs/compilerAdapters/include/compilerAdapters/cppMacrosDebug.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Some globally useful debug-only macros + Some globally useful debug-only macros */ #pragma once #ifndef COMPILERADAPTERS_CPPMACROSDEBUG_H @@ -16,11 +16,11 @@ #if DEBUG #define FILELINEPARAMSCOREUNUSED const char*, uint32_t #define FILELINEPARAMSUNUSED , FILELINEPARAMSCOREUNUSED -#define FILELINEPARAMSOPTCORE const char* szFile = __FILE__, uint32_t iLine = __LINE__ +#define FILELINEPARAMSOPTCORE const char *szFile = __FILE__, uint32_t iLine = __LINE__ #define FILELINEPARAMSOPT , FILELINEPARAMSOPTCORE #define FILELINEPARAMSOPTUNUSEDCORE const char* = __FILE__, uint32_t = __LINE__ #define FILELINEPARAMSOPTUNUSED , FILELINEPARAMSOPTUNUSEDCORE -#define FILELINEPARAMSCORE const char* szFile, uint32_t iLine +#define FILELINEPARAMSCORE const char *szFile, uint32_t iLine #define FILELINEPARAMS , FILELINEPARAMSCORE #define FILELINEVARSCORE szFile, iLine #define FILELINEVARS , FILELINEVARSCORE @@ -51,7 +51,7 @@ #if DEBUG #define Debug(e) e #define DebugOnly(e) e -#define DebugElse(s, t) s +#define DebugElse(s, t) s #define DebugList(e) (e), #define DebugParam(e) , e #define DebugFill(pb, cb) (memset((pb), 0xCC, (cb))) @@ -59,21 +59,24 @@ #define Debug(e) #define DebugOnly(e) #define DebugElse(s, t) t -#define DebugList(e) +#define DebugList(e) #define DebugParam(e) #define DebugFill(pb, cb) (1) #endif /** MsoDebugBreak can be used inside expressions. - Otherwise code should use __debugbreak() directly. + Otherwise code should use __debugbreak() directly. */ #ifdef DEBUG -__inline int32_t MsoDebugBreak(void) +__inline int32_t MsoDebugBreak(void) #ifdef __cplusplus -noexcept + noexcept #endif // __cplusplus - { __debugbreak(); return 0; } +{ + __debugbreak(); + return 0; +} #else #define MsoDebugBreak() (0) #endif diff --git a/libs/compilerAdapters/include/compilerAdapters/declspecDefinitions.h b/libs/compilerAdapters/include/compilerAdapters/declspecDefinitions.h index 674cddd..10183d7 100644 --- a/libs/compilerAdapters/include/compilerAdapters/declspecDefinitions.h +++ b/libs/compilerAdapters/include/compilerAdapters/declspecDefinitions.h @@ -2,8 +2,8 @@ // Licensed under the MIT license. /** - Cross-compiler support for declspec things - FUTURE: reconcile this with compilerFeatures.h + Cross-compiler support for declspec things + FUTURE: reconcile this with compilerFeatures.h */ #pragma once #ifndef COMPILERADAPTERS_DECLSPECDEFINITIONS_H @@ -31,14 +31,14 @@ // Latest versions of clang supports this natively #ifndef DECLSPEC_SELECTANY -#define DECLSPEC_SELECTANY __declspec(selectany) +#define DECLSPEC_SELECTANY __declspec(selectany) #endif // Mark the variable to be the first to be inited in the global init sequence. // GCC/Clang does not have init_seg, rather has a priority 101-65535 where 101 is the highest #ifndef DECLSPEC_INITFIRST #if defined(__clang__) || defined(__GNUC__) -#define DECLSPEC_INITFIRST __attribute__ ((init_priority (101))) +#define DECLSPEC_INITFIRST __attribute__((init_priority(101))) #else #define DECLSPEC_INITFIRST #endif @@ -57,18 +57,18 @@ #if defined(__clang__) || !defined(__cplusplus) || defined(__GNUC__) #define DECLSPEC_NOVTABLE #else -#define DECLSPEC_NOVTABLE __declspec(novtable) +#define DECLSPEC_NOVTABLE __declspec(novtable) #endif #endif #ifndef DECLSPEC_DEPRECATED -# if defined(__clang__) || defined(__GNUC__) -# define DECLSPEC_DEPRECATED __attribute__((deprecated)) -# elif !defined(MIDL_PASS) -# define DECLSPEC_DEPRECATED __declspec(deprecated) -# else -# define DECLSPEC_DEPRECATED -# endif +#if defined(__clang__) || defined(__GNUC__) +#define DECLSPEC_DEPRECATED __attribute__((deprecated)) +#elif !defined(MIDL_PASS) +#define DECLSPEC_DEPRECATED __declspec(deprecated) +#else +#define DECLSPEC_DEPRECATED +#endif #endif #endif // COMPILERADAPTERS_DECLSPECDEFINITIONS_H diff --git a/libs/compilerAdapters/include/compilerAdapters/functionDecorations.h b/libs/compilerAdapters/include/compilerAdapters/functionDecorations.h index cc9681a..829f1bb 100644 --- a/libs/compilerAdapters/include/compilerAdapters/functionDecorations.h +++ b/libs/compilerAdapters/include/compilerAdapters/functionDecorations.h @@ -2,61 +2,61 @@ // Licensed under the MIT license. /** - Cross-platform/language macros to decorate APIs + Cross-platform/language macros to decorate APIs */ #pragma once #ifndef COMPILERADAPTERS_FUNCTIONDECORATIONS_H #define COMPILERADAPTERS_FUNCTIONDECORATIONS_H /** - The Liblet::PublicApi attribute is used to mark a function, class or - class method as part of your public API. These are automatically - added to your export file and shim DLL. - - Note: Your liblet must be configured to process PublicApi. - Note: PublicApi replaces all MSOAPI/MSOCPPAPI-style macros. - Note: See http://aka.ms/cppdef - - Platform specific APIs are filtered using standard strings: - win, win32, win32client, win32server, winrt, android + The Liblet::PublicApi attribute is used to mark a function, class or + class method as part of your public API. These are automatically + added to your export file and shim DLL. - Usage: an API is exported for all targets - LIBLET_PUBLICAPI void MyApi() noexcept; - - Usage: exporting static methods on a class/interface - struct MyInterface - { - LIBLET_PUBLICAPI static MyInterface* Create(); - ... - }; - - Usage: platform-specific APIs - LIBLET_PUBLICAPI_EX("win32") void MyDesktop(); - LIBLET_PUBLICAPI_EX("winrt") void MyStore(); - LIBLET_PUBLICAPI_EX("win32", "android") void MyApi(); - - Note: LIBLET_PUBLICAPI_EX(...) is not supported on Apple platforms, - Use LIBLET_PUBLICAPI_APPLE instead. - LIBLET_PUBLICAPI_EX("winrt") LIBLET_PUBLICAPI_APPLE void MyApi(); + Note: Your liblet must be configured to process PublicApi. + Note: PublicApi replaces all MSOAPI/MSOCPPAPI-style macros. + Note: See http://aka.ms/cppdef - Usage: export a whole class (heavily discouraged) - struct LIBLET_PUBLICAPI MyExportedClass - { - // override default class export - LIBLET_PUBLICAPI_EX("win32") void MyDesktop(); + Platform specific APIs are filtered using standard strings: + win, win32, win32client, win32server, winrt, android - void AlsoExported(); - }; - - Usage: export special data types from a class (android + apple only) - Values: "typeinfo", "typeinfoname", "vtable", "thunks" - struct LIBLET_PUBLICAPI_CLASSDATA("typeinfo") MyClass - { - }; + Usage: an API is exported for all targets + LIBLET_PUBLICAPI void MyApi() noexcept; - struct LIBLET_PUBLICAPI_CLASSDATA("typeinfo", "vtable") MyClass - { - }; + Usage: exporting static methods on a class/interface + struct MyInterface + { + LIBLET_PUBLICAPI static MyInterface* Create(); + ... + }; + + Usage: platform-specific APIs + LIBLET_PUBLICAPI_EX("win32") void MyDesktop(); + LIBLET_PUBLICAPI_EX("winrt") void MyStore(); + LIBLET_PUBLICAPI_EX("win32", "android") void MyApi(); + + Note: LIBLET_PUBLICAPI_EX(...) is not supported on Apple platforms, + Use LIBLET_PUBLICAPI_APPLE instead. + LIBLET_PUBLICAPI_EX("winrt") LIBLET_PUBLICAPI_APPLE void MyApi(); + + Usage: export a whole class (heavily discouraged) + struct LIBLET_PUBLICAPI MyExportedClass + { + // override default class export + LIBLET_PUBLICAPI_EX("win32") void MyDesktop(); + + void AlsoExported(); + }; + + Usage: export special data types from a class (android + apple only) + Values: "typeinfo", "typeinfoname", "vtable", "thunks" + struct LIBLET_PUBLICAPI_CLASSDATA("typeinfo") MyClass + { + }; + + struct LIBLET_PUBLICAPI_CLASSDATA("typeinfo", "vtable") MyClass + { + }; */ #if defined(__clangpluginrunner__) #define LIBLET_PUBLICAPI [[Liblet::PublicApi]] @@ -85,19 +85,19 @@ #endif /** - The Liblet::MockName macro enables renaming of the generated mock names. - This is useful when the function / interface method is overloaded. - - struct IBank - { - // Generate mock_TryWithdrawlUint32 - LIBLET_MOCKNAME("TryWithdrawlUint32") - virtual bool TryWithdrawl(uint32_t amount) = 0; + The Liblet::MockName macro enables renaming of the generated mock names. + This is useful when the function / interface method is overloaded. - // Generate mock_TryWithdrawlFloat - LIBLET_MOCKNAME("TryWithdrawlFloat") - virtual bool TryWithdrawl(float amount) = 0; - }; + struct IBank + { + // Generate mock_TryWithdrawlUint32 + LIBLET_MOCKNAME("TryWithdrawlUint32") + virtual bool TryWithdrawl(uint32_t amount) = 0; + + // Generate mock_TryWithdrawlFloat + LIBLET_MOCKNAME("TryWithdrawlFloat") + virtual bool TryWithdrawl(float amount) = 0; + }; */ #if defined(__clangpluginrunner__) #define LIBLET_MOCKNAME(name) [[Liblet::MockName(name)]] @@ -106,21 +106,23 @@ #endif /** - Macros for extern "C" that support C & C++ + Macros for extern "C" that support C & C++ */ #if defined(__cplusplus) #define MSOEXTERN_C extern "C" -#define MSOEXTERN_C_BEGIN extern "C" { +#define MSOEXTERN_C_BEGIN \ + extern "C" \ + { #define MSOEXTERN_C_END } #else -#define MSOEXTERN_C +#define MSOEXTERN_C #define MSOEXTERN_C_BEGIN #define MSOEXTERN_C_END #endif /** - Macro for constexpr - FUTURE: VC14 supports constexpr + Macro for constexpr + FUTURE: VC14 supports constexpr */ #if defined(__cplusplus) && defined(__clang__) #define MSOCONSTEXPR constexpr @@ -129,7 +131,7 @@ #endif /** - Macros to use nothrow/throw not on clang + Macros to use nothrow/throw not on clang */ #if defined(__cplusplus) && !defined(__clang__) /* SSS_WARNINGS_OFF */ @@ -140,7 +142,7 @@ #endif // C++ /** - Macro to enable noexcept only for C++ + Macro to enable noexcept only for C++ */ #if defined(__cplusplus) #define MSONOEXCEPT noexcept @@ -149,25 +151,25 @@ #endif // C++ /** - Macro to mark a method as const for C & C++ + Macro to mark a method as const for C & C++ */ #if defined(__cplusplus) && !defined(CINTERFACE) - #define CONST_METHOD const +#define CONST_METHOD const #else - #define CONST_METHOD +#define CONST_METHOD #endif /** - Utility macro to make writing NonConst versions of functions easier. - In C, you can't overload functions; thus the two flavors of a function will be - DoSomething - DoSomethingNonConst - In C++, you can overload functions, so the two flavors of a function will have - the same name (but with different arguments). + Utility macro to make writing NonConst versions of functions easier. + In C, you can't overload functions; thus the two flavors of a function will be + DoSomething + DoSomethingNonConst + In C++, you can overload functions, so the two flavors of a function will have + the same name (but with different arguments). - To work around this, declare the second function as NON_CONST_VER(DoSomething) - This also can be used when you explicitly want to call the nonConst version from - an inline function that can be compiled as either C or C++ + To work around this, declare the second function as NON_CONST_VER(DoSomething) + This also can be used when you explicitly want to call the nonConst version from + an inline function that can be compiled as either C or C++ */ #if defined(__cplusplus) #define NON_CONST_VER(Function) Function @@ -177,7 +179,7 @@ #define NON_CONST_VER_DECL(Function) NON_CONST_VER(Function) /** - Macro to use __forceinline with cl.exe + Macro to use __forceinline with cl.exe */ /* SSS_WARNINGS_OFF */ #if defined(__cplusplus) && !defined(__clang__) @@ -188,14 +190,14 @@ /* SSS_WARNINGS_ON */ #if defined(__clang__) - #define MSO_NO_INLINE __attribute__((noinline)) +#define MSO_NO_INLINE __attribute__((noinline)) #else - #define MSO_NO_INLINE __declspec(noinline) +#define MSO_NO_INLINE __declspec(noinline) #endif /** - Clang forbids the use of static with friend. - msvc issues warning C4211: nonstandard extension used: redefined extern to static without it + Clang forbids the use of static with friend. + msvc issues warning C4211: nonstandard extension used: redefined extern to static without it */ #if defined(__clang__) #define MSO_STATIC_FRIEND friend @@ -203,26 +205,25 @@ #define MSO_STATIC_FRIEND friend static #endif - // Don't use any of these macros, they are being eliminated // The definitions are a mess to prevent removed macros from sneaking back in #if defined(__cplusplus) && !defined(__clang__) /* SSS_WARNINGS_OFF */ -#define MSOCPPAPI_(t) extern "C++" __declspec(nothrow) t __cdecl +#define MSOCPPAPI_(t) extern "C++" __declspec(nothrow) t __cdecl #if defined(_M_X64) -#define MSOAPI_(t) MSOEXTERN_C __declspec(nothrow) t __fastcall +#define MSOAPI_(t) MSOEXTERN_C __declspec(nothrow) t __fastcall #else -#define MSOAPI_(t) MSOEXTERN_C __declspec(nothrow) t __stdcall +#define MSOAPI_(t) MSOEXTERN_C __declspec(nothrow) t __stdcall #endif /* SSS_WARNINGS_ON */ #else -#define MSOCPPAPI_(t) extern "C++" t __cdecl +#define MSOCPPAPI_(t) extern "C++" t __cdecl #if defined(_M_X64) -#define MSOAPI_(t) MSOEXTERN_C t __fastcall +#define MSOAPI_(t) MSOEXTERN_C t __fastcall #else -#define MSOAPI_(t) MSOEXTERN_C t __stdcall +#define MSOAPI_(t) MSOEXTERN_C t __stdcall #endif #endif diff --git a/libs/compilerAdapters/include/compilerAdapters/intrinsics.h b/libs/compilerAdapters/include/compilerAdapters/intrinsics.h index dd66c65..1238d54 100644 --- a/libs/compilerAdapters/include/compilerAdapters/intrinsics.h +++ b/libs/compilerAdapters/include/compilerAdapters/intrinsics.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Adapters for various compiler intrinsics + Adapters for various compiler intrinsics */ #pragma once #ifndef COMPILERADAPTERS_INTRINSICS_H @@ -10,12 +10,12 @@ /** Macro that calls compiler intrinsics to terminate the application and bypass all exception handlers */ #if defined(__clang__) || defined(__GNUC__) - #define MSOFASTFAIL(arg) __builtin_trap() - #define MSO_FUNC_RETURN_ADDRESS() __builtin_return_address(0) +#define MSOFASTFAIL(arg) __builtin_trap() +#define MSO_FUNC_RETURN_ADDRESS() __builtin_return_address(0) #else - #include - #define MSOFASTFAIL(arg) __fastfail(arg) - #define MSO_FUNC_RETURN_ADDRESS() _ReturnAddress() +#include +#define MSOFASTFAIL(arg) __fastfail(arg) +#define MSO_FUNC_RETURN_ADDRESS() _ReturnAddress() #endif #endif diff --git a/libs/compilerAdapters/include/compilerAdapters/linker.h b/libs/compilerAdapters/include/compilerAdapters/linker.h index b26f2c8..ef5d1e3 100644 --- a/libs/compilerAdapters/include/compilerAdapters/linker.h +++ b/libs/compilerAdapters/include/compilerAdapters/linker.h @@ -2,29 +2,30 @@ // Licensed under the MIT license. /** - Things related to linking + Things related to linking */ #pragma once #ifndef COMPILERADAPTERS_LINKER_H #define COMPILERADAPTERS_LINKER_H /** - If a library has no direct entry points, it may be necessary to force - the linker to include it. There are two ways to accomplish this: + If a library has no direct entry points, it may be necessary to force + the linker to include it. There are two ways to accomplish this: - 1) Preferably - link the library as a LOB instead. + 1) Preferably - link the library as a LOB instead. - 2) Use MSO_DEFINE_SYMBOL to define a symbol in the source file that needs to - be included. Then, add the corresponding MSO_LINK_SYMBOL macro to one of the - source files that gets compiled directly into your binary (as an *.obj file) + 2) Use MSO_DEFINE_SYMBOL to define a symbol in the source file that needs to + be included. Then, add the corresponding MSO_LINK_SYMBOL macro to one of the + source files that gets compiled directly into your binary (as an *.obj file) */ -#define MSO_DEFINE_SYMBOL(symbol) extern "C" void __cdecl symbol() {} +#define MSO_DEFINE_SYMBOL(symbol) \ + extern "C" void __cdecl symbol() {} // MSO_LINK_INCLUDE and MSO_LINK_SYMBOL macros are only needed for MSVC. #if MS_TARGET_WINDOWS /** - Machinery for the MSO_LINK_SYMBOL macro + Machinery for the MSO_LINK_SYMBOL macro */ #if defined(_M_HYBRID) #define MSO_LINK_INCLUDE(symbol) "/INCLUDE:#" symbol @@ -37,24 +38,24 @@ #endif /** - See MSO_DEFINE_SYMBOL above + See MSO_DEFINE_SYMBOL above */ -#define MSO_LINK_SYMBOL( symbol ) __pragma( comment( linker, MSO_LINK_INCLUDE( #symbol ) ) ) +#define MSO_LINK_SYMBOL(symbol) __pragma(comment(linker, MSO_LINK_INCLUDE(#symbol))) /** - Platform-agnostic macro to define dll export name ("foo" vs "_foo@4") - The number is generally [# of params * 4]. + Platform-agnostic macro to define dll export name ("foo" vs "_foo@4") + The number is generally [# of params * 4]. - Note: using GetProcAddress is usually wrong. Prefer linker delay-loading. + Note: using GetProcAddress is usually wrong. Prefer linker delay-loading. - Example: - void Foo(int bar); - auto pFoo = (decltype(Foo) *) GetProcAddress(hMod, SzDllExport("Foo", 4)); + Example: + void Foo(int bar); + auto pFoo = (decltype(Foo) *) GetProcAddress(hMod, SzDllExport("Foo", 4)); */ #if defined(_M_X64) || defined(_M_ARM) -#define SzDllExport( fn, c ) fn +#define SzDllExport(fn, c) fn #elif defined(_M_IX86) -#define SzDllExport( fn, c ) "_" fn "@" #c +#define SzDllExport(fn, c) "_" fn "@" #c #else #error Unknown Platform! #endif // x64 || _M_ARM diff --git a/libs/compilerAdapters/include/compilerAdapters/managedCpp.h b/libs/compilerAdapters/include/compilerAdapters/managedCpp.h index cffc0eb..1b9da13 100644 --- a/libs/compilerAdapters/include/compilerAdapters/managedCpp.h +++ b/libs/compilerAdapters/include/compilerAdapters/managedCpp.h @@ -2,22 +2,22 @@ // Licensed under the MIT license. /** - Support for managed C++ compilation available only in VC++. + Support for managed C++ compilation available only in VC++. */ #pragma once #ifndef COMPILERADAPTERS_MANAGEDCPP_H #define COMPILERADAPTERS_MANAGEDCPP_H /** - VC++ specific pragmas to indicate that code must not be compiled as managed. - Functions are compiled as managed by default when /clr is used. - The pragmas below allow explicitly indicate that code is unmanaged, but these - pragmas are not recognized by Clang compiler. + VC++ specific pragmas to indicate that code must not be compiled as managed. + Functions are compiled as managed by default when /clr is used. + The pragmas below allow explicitly indicate that code is unmanaged, but these + pragmas are not recognized by Clang compiler. */ #if !defined(__clang__) #define MSO_PRAGMA_MANAGED_PUSH_OFF __pragma(managed(push, off)) -#define MSO_PRAGMA_MANAGED_POP __pragma(managed(pop)) +#define MSO_PRAGMA_MANAGED_POP __pragma(managed(pop)) #else // !defined(__clang__) diff --git a/libs/cppExtensions/include/cppExtensions/autoRestore.h b/libs/cppExtensions/include/cppExtensions/autoRestore.h index 78677ee..9c6f939 100644 --- a/libs/cppExtensions/include/cppExtensions/autoRestore.h +++ b/libs/cppExtensions/include/cppExtensions/autoRestore.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Helper classes to automatically restore/cleanup/undo an operation. + Helper classes to automatically restore/cleanup/undo an operation. */ #ifndef _CPPEXTENSIONS_AUTORESTORE_H_ #define _CPPEXTENSIONS_AUTORESTORE_H_ @@ -15,224 +15,244 @@ // 4472: 'pointer_safety' is a native enum: add an access specifier (private/public) to declare a managed enum // 4996: 'wmemcpy': This function or variable may be unsafe. Consider using wmemcpy_s instead #pragma warning(push) -#pragma warning(disable: 4091 4472 4996) +#pragma warning(disable : 4091 4472 4996) #include #pragma warning(pop) // 4996: 'wmemcpy': This function or variable may be unsafe. Consider using wmemcpy_s instead #pragma warning(push) -#pragma warning(disable: 4996) +#pragma warning(disable : 4996) #include #pragma warning(pop) namespace Mso { /** - Restores a variable to its original value in an exception-safe way. - For example: - { - Mso::TRestorer restoreFlag(m_fFlag, true); - ... // do something that might throw an exception - } // m_fFlag is automatically restored to its original value + Restores a variable to its original value in an exception-safe way. + For example: + { + Mso::TRestorer restoreFlag(m_fFlag, true); + ... // do something that might throw an exception + } // m_fFlag is automatically restored to its original value */ -template class TRestorer +template +class TRestorer { public: - TRestorer(T& value) noexcept : m_pValue(std::addressof(value)), m_previousValue(value) {} - TRestorer(T& value, T newValue) noexcept : m_pValue(std::addressof(value)), m_previousValue(value) - { *m_pValue = newValue; } - TRestorer(TRestorer&& other) noexcept : m_pValue(other.m_pValue), m_previousValue(other.m_previousValue) - { other.Disable(); } - ~TRestorer() noexcept { *m_pValue = m_previousValue; } + TRestorer(T& value) noexcept : m_pValue(std::addressof(value)), m_previousValue(value) {} + TRestorer(T& value, T newValue) noexcept : m_pValue(std::addressof(value)), m_previousValue(value) + { + *m_pValue = newValue; + } + TRestorer(TRestorer&& other) noexcept : m_pValue(other.m_pValue), m_previousValue(other.m_previousValue) + { + other.Disable(); + } + ~TRestorer() noexcept + { + *m_pValue = m_previousValue; + } - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TRestorer); - TRestorer& operator=(TRestorer&& other) noexcept = delete; + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TRestorer); + TRestorer& operator=(TRestorer&& other) noexcept = delete; - bool IsEnabled() noexcept { return (m_pValue != std::addressof(m_previousValue)); } - void Disable() noexcept { m_pValue = std::addressof(m_previousValue); } + bool IsEnabled() noexcept + { + return (m_pValue != std::addressof(m_previousValue)); + } + void Disable() noexcept + { + m_pValue = std::addressof(m_previousValue); + } private: - T* m_pValue; - T m_previousValue; + T* m_pValue; + T m_previousValue; }; /** - AutoRestorer() can be used to avoid being explicit with TRestorer + AutoRestorer() can be used to avoid being explicit with TRestorer - Instead of: - Mso::TRestorer restorer(m_inLayout); - Do this: - auto restorer = Mso::AutoRestorer(m_inLayout); + Instead of: + Mso::TRestorer restorer(m_inLayout); + Do this: + auto restorer = Mso::AutoRestorer(m_inLayout); */ template -Mso::TRestorer AutoRestorer(T &value) noexcept +Mso::TRestorer AutoRestorer(T& value) noexcept { - return Mso::TRestorer(value); + return Mso::TRestorer(value); } template -Mso::TRestorer AutoRestorer(T &value, T newValue) noexcept +Mso::TRestorer AutoRestorer(T& value, T newValue) noexcept { - return Mso::TRestorer(value, newValue); + return Mso::TRestorer(value, newValue); } - /** - Restores a value to its original value (using a getter/setter) in an exception-safe way. For example: + Restores a value to its original value (using a getter/setter) in an exception-safe way. For example: - Foo* GetGlobalFoo() - { - return s_pFooGlobal; - } + Foo* GetGlobalFoo() + { + return s_pFooGlobal; + } - void SetGlobalFoo(Foo* pFoo) - { - s_pFooGlobal = pFoo; - } + void SetGlobalFoo(Foo* pFoo) + { + s_pFooGlobal = pFoo; + } - using GlobalFooRestorer = Mso::TPropertyRestorer; + using GlobalFooRestorer = Mso::TPropertyRestorer; - void MyMethod(Foo* pFoo) - { - GlobalFooRestorer rstGlobalFoo(pFoo); - ... // do something that might throw an exception - } // s_pFooGlobal is automatically restored to its original value + void MyMethod(Foo* pFoo) + { + GlobalFooRestorer rstGlobalFoo(pFoo); + ... // do something that might throw an exception + } // s_pFooGlobal is automatically restored to its original value */ -template< - typename T, - T PfnGetter(), - void PfnSetter(T value)> +template struct TPropertyRestorer final { public: - TPropertyRestorer() = default; - TPropertyRestorer(T newValue) noexcept(noexcept(PfnSetter(PfnGetter()))) // noexcept(any expression with both Get and Set) - { - PfnSetter(std::forward(newValue)); - } - TPropertyRestorer(TPropertyRestorer&& other) noexcept : - m_isDisabled(other.m_isDisabled), - m_valueToRestore(std::forward(other.m_valueToRestore)) - { - other.Disable(); - } + TPropertyRestorer() = default; + TPropertyRestorer(T newValue) noexcept( + noexcept(PfnSetter(PfnGetter()))) // noexcept(any expression with both Get and Set) + { + PfnSetter(std::forward(newValue)); + } + TPropertyRestorer(TPropertyRestorer&& other) noexcept + : m_isDisabled(other.m_isDisabled), m_valueToRestore(std::forward(other.m_valueToRestore)) + { + other.Disable(); + } - ~TPropertyRestorer() - { - if (!m_isDisabled) - { - PfnSetter(std::forward(m_valueToRestore)); - } - } + ~TPropertyRestorer() + { + if (!m_isDisabled) + { + PfnSetter(std::forward(m_valueToRestore)); + } + } - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TPropertyRestorer); // No copying! + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TPropertyRestorer); // No copying! - template::type>::value, TSelf>> - TSelf& operator=(TSelf&& other) noexcept - { - if (this != &other) - { - m_isDisabled = other.m_isDisabled; - m_valueToRestore = std::move(other.m_valueToRestore); + template < + typename TSelf = TPropertyRestorer, + typename = + typename std::enable_if_t::type>::value, TSelf>> + TSelf& operator=(TSelf&& other) noexcept + { + if (this != &other) + { + m_isDisabled = other.m_isDisabled; + m_valueToRestore = std::move(other.m_valueToRestore); - other.Disable(); - } + other.Disable(); + } - return *this; - } + return *this; + } - bool IsEnabled() const noexcept { return !m_isDisabled; } - void Disable() noexcept { m_isDisabled = true; } + bool IsEnabled() const noexcept + { + return !m_isDisabled; + } + void Disable() noexcept + { + m_isDisabled = true; + } - T& ValueToRestore() noexcept { return m_valueToRestore; } + T& ValueToRestore() noexcept + { + return m_valueToRestore; + } private: - bool m_isDisabled = false; - T m_valueToRestore{PfnGetter()}; + bool m_isDisabled = false; + T m_valueToRestore{PfnGetter()}; }; - -namespace TCleanup -{ +namespace TCleanup { /** - TCleanup - The last resort. If none of the other helper classes work for you, - or there is only a single occurrence that you feel doesn't warrant its own - helper class, the cleanup lambda option is available. + TCleanup + The last resort. If none of the other helper classes work for you, + or there is only a single occurrence that you feel doesn't warrant its own + helper class, the cleanup lambda option is available. - Runs the passed cleanup function on destruction. - This is a handy utility to use previous "goto LError" style cleanup code - with the early return pattern. + Runs the passed cleanup function on destruction. + This is a handy utility to use previous "goto LError" style cleanup code + with the early return pattern. - EXAMPLE: - // Specify the code to run on return in a capture-by-reference lambda - auto cleanupCloseOLDoc = TCleanup::Make([&m_pOrigFile, &m_pNewFile] - { - // Close out the local file if appropriate - if (m_pOrigFile != m_pNewFile && m_pNewFile->GetOpenCount()) - { - m_pNewFile->BeginCmd(msoiolcmdClose); - m_pNewFile->RecordEvent(msoiolevtCmdCompleted); - } - }); + EXAMPLE: + // Specify the code to run on return in a capture-by-reference lambda + auto cleanupCloseOLDoc = TCleanup::Make([&m_pOrigFile, &m_pNewFile] + { + // Close out the local file if appropriate + if (m_pOrigFile != m_pNewFile && m_pNewFile->GetOpenCount()) + { + m_pNewFile->BeginCmd(msoiolcmdClose); + m_pNewFile->RecordEvent(msoiolevtCmdCompleted); + } + }); - hr = /some code that uses and OLDocument/; - if (FAILED(hr)) - return hr; - // Runs the cleanup code above before returning + hr = /some code that uses and OLDocument/; + if (FAILED(hr)) + return hr; + // Runs the cleanup code above before returning - If you want to be able to disable the TCleanup from running on exit, - you can do so by: + If you want to be able to disable the TCleanup from running on exit, + you can do so by: - if (/some condition/) - cleanupCloseOLDoc.disable(); // The TCleanup will now not run on exit + if (/some condition/) + cleanupCloseOLDoc.disable(); // The TCleanup will now not run on exit */ -template +template struct TCleanup { public: - explicit TCleanup(const Func& fnCleanup) noexcept : - m_fnCleanup(fnCleanup) - {} + explicit TCleanup(const Func& fnCleanup) noexcept : m_fnCleanup(fnCleanup) {} - explicit TCleanup(Func&& fnCleanup) noexcept : - m_fnCleanup(std::move(fnCleanup)) - {} + explicit TCleanup(Func&& fnCleanup) noexcept : m_fnCleanup(std::move(fnCleanup)) {} - TCleanup(TCleanup&& rVal) noexcept : - m_fnCleanup(rVal.m_fnCleanup), - m_isEnabled(rVal.m_isEnabled) - { - // We don't want to run the cleanup twice, so disable the original - rVal.disable(); - } + TCleanup(TCleanup&& rVal) noexcept : m_fnCleanup(rVal.m_fnCleanup), m_isEnabled(rVal.m_isEnabled) + { + // We don't want to run the cleanup twice, so disable the original + rVal.disable(); + } - ~TCleanup() noexcept - { - if (m_isEnabled) - m_fnCleanup(); - } + ~TCleanup() noexcept + { + if (m_isEnabled) + m_fnCleanup(); + } - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TCleanup); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TCleanup); - void enable() noexcept { m_isEnabled = true; } - void disable() noexcept { m_isEnabled = false; } + void enable() noexcept + { + m_isEnabled = true; + } + void disable() noexcept + { + m_isEnabled = false; + } private: - const Func m_fnCleanup; - bool m_isEnabled = true; + const Func m_fnCleanup; + bool m_isEnabled = true; }; // Constructs a TCleanup from the passed function or lambda -template +template inline TCleanup Make(const Func& pfnCleanup) noexcept { - return TCleanup(pfnCleanup); + return TCleanup(pfnCleanup); } -} // end TCleanup namespace +} // namespace TCleanup -} // Mso +} // namespace Mso #endif // __cplusplus diff --git a/libs/cppExtensions/include/cppExtensions/stringLiteral.h b/libs/cppExtensions/include/cppExtensions/stringLiteral.h index 39197a7..f37e98f 100644 --- a/libs/cppExtensions/include/cppExtensions/stringLiteral.h +++ b/libs/cppExtensions/include/cppExtensions/stringLiteral.h @@ -2,14 +2,14 @@ // Licensed under the MIT license. /** - Use this type to enforce that an actual literal string is provided. - - void DoSomething(const StringLiteral& input) { s_name = input; } - - DoSomething("Hi"_S); - - To use this class and _S, you need to pull in the namespace. - using namespace Mso::StringLiterals; + Use this type to enforce that an actual literal string is provided. + + void DoSomething(const StringLiteral& input) { s_name = input; } + + DoSomething("Hi"_S); + + To use this class and _S, you need to pull in the namespace. + using namespace Mso::StringLiterals; */ #ifndef _CPPEXTENSIONS_STRINGLITERAL_H_ @@ -19,92 +19,94 @@ #include #include -namespace Mso { -namespace StringLiterals { +namespace Mso { namespace StringLiterals { -template +template class StringLiteral; constexpr StringLiteral operator""_S(const char* str, size_t) noexcept; /** - StringLiteral can only be constructed using the user-defined-literal operators below. + StringLiteral can only be constructed using the user-defined-literal operators below. */ -template +template class StringLiteral { public: - constexpr operator _Null_terminated_ const char_type*() const noexcept { return m_string; } + constexpr operator _Null_terminated_ const char_type *() const noexcept + { + return m_string; + } - constexpr size_t length() const noexcept - { - // std::char_traits<>::length() is preferred, but it's not constexpr (even though it optimizes away). - // note: using recursion until next version of msvc compiler which supports loops - return length_worker(m_string); - } + constexpr size_t length() const noexcept + { + // std::char_traits<>::length() is preferred, but it's not constexpr (even though it optimizes away). + // note: using recursion until next version of msvc compiler which supports loops + return length_worker(m_string); + } - constexpr const char_type* const* operator&() const noexcept { return &m_string; } - -//private: - constexpr StringLiteral(_In_z_ const char_type* str) noexcept : m_string(str) - { - } - - constexpr static size_t length_worker(_In_z_ const char_type* str) noexcept - { - return *str ? length_worker(str + 1) + 1 : 0; - } + constexpr const char_type* const* operator&() const noexcept + { + return &m_string; + } - const char_type* const m_string; + // private: + constexpr StringLiteral(_In_z_ const char_type* str) noexcept : m_string(str) {} - //friend constexpr StringLiteral operator""_S(const char*, size_t) noexcept; - // friend constexpr StringLiteral operator""_S(const wchar_t*, size_t); - // friend constexpr StringLiteral operator""_S(const char16_t*, size_t); - // friend constexpr StringLiteral operator""_S(const char32_t*, size_t); + constexpr static size_t length_worker(_In_z_ const char_type* str) noexcept + { + return *str ? length_worker(str + 1) + 1 : 0; + } + + const char_type* const m_string; + + // friend constexpr StringLiteral operator""_S(const char*, size_t) noexcept; + // friend constexpr StringLiteral operator""_S(const wchar_t*, size_t); + // friend constexpr StringLiteral operator""_S(const char16_t*, size_t); + // friend constexpr StringLiteral operator""_S(const char32_t*, size_t); }; constexpr StringLiteral operator""_S(const char* str, size_t) noexcept { - return { str }; + return {str}; } inline constexpr StringLiteral operator""_S(const wchar_t* str, size_t) noexcept { - return { str }; + return {str}; } inline constexpr StringLiteral operator""_S(const char16_t* str, size_t) noexcept { - return { str }; + return {str}; } inline constexpr StringLiteral operator""_S(const char32_t* str, size_t) noexcept { - return { str }; + return {str}; } /** - Special tag used with overloads accepting a raw string pointer. + Special tag used with overloads accepting a raw string pointer. - struct HoldSomething - { - HoldSomething(const StringLiteral& input) : m_string(input) {} - HoldSomething(const char* input, const NonStringLiteral_lifetime_semantics_reviewed&) : m_string(input) {} - - private: const char* m_string = nullptr; - }; - - void SafeCall() - { - const char* sz = GetName(); - HoldSomething h(sz, NonStringLiteral_lifetime_semantics_reviewed); - } + struct HoldSomething + { + HoldSomething(const StringLiteral& input) : m_string(input) {} + HoldSomething(const char* input, const NonStringLiteral_lifetime_semantics_reviewed&) : m_string(input) {} + + private: const char* m_string = nullptr; + }; + + void SafeCall() + { + const char* sz = GetName(); + HoldSomething h(sz, NonStringLiteral_lifetime_semantics_reviewed); + } */ constexpr struct NonStringLiteral_lifetime_semantics_reviewed_t { -} NonStringLiteral_lifetime_semantics_reviewed {}; +} NonStringLiteral_lifetime_semantics_reviewed{}; -} // StringLiterals -} // Mso +}} // namespace Mso::StringLiterals #endif // _CPPEXTENSIONS_STRINGLITERAL_H_ diff --git a/libs/cppExtensions/include/cppExtensions/threadLocal_fls.h b/libs/cppExtensions/include/cppExtensions/threadLocal_fls.h index ce8a30b..ba2a4cf 100644 --- a/libs/cppExtensions/include/cppExtensions/threadLocal_fls.h +++ b/libs/cppExtensions/include/cppExtensions/threadLocal_fls.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - FLS-based implementation of TLS + FLS-based implementation of TLS */ #ifndef _CPPEXTENSIONS_THREADLOCAL_FLS_H_ #define _CPPEXTENSIONS_THREADLOCAL_FLS_H_ @@ -16,67 +16,65 @@ namespace Mso { namespace Details { struct ThreadLocalImpl { - DECLARE_COPYCONSTR_AND_ASSIGNMENT(ThreadLocalImpl); - static_assert(FLS_OUT_OF_INDEXES == TLS_OUT_OF_INDEXES, "Assumption violation"); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(ThreadLocalImpl); + static_assert(FLS_OUT_OF_INDEXES == TLS_OUT_OF_INDEXES, "Assumption violation"); - ThreadLocalImpl() noexcept : ThreadLocalImpl(nullptr) - { - } + ThreadLocalImpl() noexcept : ThreadLocalImpl(nullptr) {} - /** - Callback will be invoked with the TLS data on each thread exit - */ - ThreadLocalImpl(void (__stdcall *pfnCleanup)(void*) noexcept) noexcept - { - if (pfnCleanup) - { - m_index = ::FlsAlloc(pfnCleanup); - m_isFls = true; - } - else - { - m_index = ::TlsAlloc(); - } + /** + Callback will be invoked with the TLS data on each thread exit + */ + ThreadLocalImpl(void(__stdcall* pfnCleanup)(void*) noexcept) noexcept + { + if (pfnCleanup) + { + m_index = ::FlsAlloc(pfnCleanup); + m_isFls = true; + } + else + { + m_index = ::TlsAlloc(); + } - CheckFatal(m_index != TLS_OUT_OF_INDEXES); - } + CheckFatal(m_index != TLS_OUT_OF_INDEXES); + } - ~ThreadLocalImpl() noexcept - { - if (m_isFls) - ::FlsFree(m_index); - else - ::TlsFree(m_index); - } + ~ThreadLocalImpl() noexcept + { + if (m_isFls) + ::FlsFree(m_index); + else + ::TlsFree(m_index); + } - void* Get() const noexcept - { - if (m_isFls) - return ::FlsGetValue(m_index); - else - return ::TlsGetValue(m_index); - } + void* Get() const noexcept + { + if (m_isFls) + return ::FlsGetValue(m_index); + else + return ::TlsGetValue(m_index); + } - void Set(void* t) noexcept - { - if (m_isFls) - CheckFatal(!!::FlsSetValue(m_index, t)); - else - CheckFatal(!!::TlsSetValue(m_index, t)); - } + void Set(void* t) noexcept + { + if (m_isFls) + CheckFatal(!!::FlsSetValue(m_index, t)); + else + CheckFatal(!!::TlsSetValue(m_index, t)); + } private: - static void CheckFatal(bool result) noexcept - { - if (!result) - __fastfail(FAST_FAIL_FATAL_APP_EXIT); - } + static void CheckFatal(bool result) noexcept + { + if (!result) + __fastfail(FAST_FAIL_FATAL_APP_EXIT); + } - uint32_t m_index = TLS_OUT_OF_INDEXES; - bool m_isFls = false; + uint32_t m_index = TLS_OUT_OF_INDEXES; + bool m_isFls = false; }; -}} // Mso::Details +}} // namespace Mso::Details #endif // __cplusplus #endif // _CPPEXTENSIONS_THREADLOCAL_FLS_H_ diff --git a/libs/cppExtensions/include/cppExtensions/threadLocal_pthread.h b/libs/cppExtensions/include/cppExtensions/threadLocal_pthread.h index e67ff6d..91b942a 100644 --- a/libs/cppExtensions/include/cppExtensions/threadLocal_pthread.h +++ b/libs/cppExtensions/include/cppExtensions/threadLocal_pthread.h @@ -13,41 +13,41 @@ namespace Mso { namespace Details { struct ThreadLocalImpl { - DECLARE_COPYCONSTR_AND_ASSIGNMENT(ThreadLocalImpl); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(ThreadLocalImpl); - ThreadLocalImpl() noexcept - { - if (pthread_key_create(&m_pthread_key, nullptr) != 0) - std::abort(); - } + ThreadLocalImpl() noexcept + { + if (pthread_key_create(&m_pthread_key, nullptr) != 0) + std::abort(); + } - ThreadLocalImpl(void (*pfnCleanup)(void*) noexcept) noexcept - { - if (pthread_key_create(&m_pthread_key, pfnCleanup) != 0) - std::abort(); - } + ThreadLocalImpl(void (*pfnCleanup)(void*) noexcept) noexcept + { + if (pthread_key_create(&m_pthread_key, pfnCleanup) != 0) + std::abort(); + } - ~ThreadLocalImpl() noexcept - { - if (m_pthread_key) - pthread_key_delete(m_pthread_key); - } + ~ThreadLocalImpl() noexcept + { + if (m_pthread_key) + pthread_key_delete(m_pthread_key); + } - void* Get() const noexcept - { - return pthread_getspecific(m_pthread_key); - } - - void Set(const void* t) noexcept - { - if (pthread_setspecific(m_pthread_key, t) != 0) - std::abort(); - } + void* Get() const noexcept + { + return pthread_getspecific(m_pthread_key); + } + + void Set(const void* t) noexcept + { + if (pthread_setspecific(m_pthread_key, t) != 0) + std::abort(); + } private: - pthread_key_t m_pthread_key {}; + pthread_key_t m_pthread_key{}; }; -}} // Mso::Details +}} // namespace Mso::Details #endif // _CPPEXTENSIONS_THREADLOCAL_PTHREAD_H_ diff --git a/libs/cppExtensions/tests/autoRestoreTest.cpp b/libs/cppExtensions/tests/autoRestoreTest.cpp index 464727e..b73d2be 100644 --- a/libs/cppExtensions/tests/autoRestoreTest.cpp +++ b/libs/cppExtensions/tests/autoRestoreTest.cpp @@ -8,41 +8,40 @@ Basic testing for Mso::TPropertyRestorer #include #include -template +template struct TestProperty { - static T Get() noexcept - { - static typename std::decay::type s_value; - return std::forward(s_value); // Return any value that compiles. - } + static T Get() noexcept + { + static typename std::decay::type s_value; + return std::forward(s_value); // Return any value that compiles. + } - static void Set(T /*value*/) noexcept - { - } + static void Set(T /*value*/) noexcept {} - using Restorer = typename Mso::TPropertyRestorer; + using Restorer = typename Mso::TPropertyRestorer; - template - static void VerifyRestorerCompiles() noexcept - { - Restorer rst(Get()); // Ensure class template instantiation compiles. - Restorer rst2(std::move(rst)); // Ensure move semantics compile too. + template + static void VerifyRestorerCompiles() noexcept + { + Restorer rst(Get()); // Ensure class template instantiation compiles. + Restorer rst2(std::move(rst)); // Ensure move semantics compile too. - rst = std::move(rst2); - } + rst = std::move(rst2); + } - template<> - static void VerifyRestorerCompiles() noexcept - { - Restorer rst(Get()); // Ensure class template instantiation compiles. - Restorer rst2(std::move(rst)); // Ensure move semantics compile too. + template <> + static void VerifyRestorerCompiles() noexcept + { + Restorer rst(Get()); // Ensure class template instantiation compiles. + Restorer rst2(std::move(rst)); // Ensure move semantics compile too. - static_assert(!std::is_move_assignable::value, "If T has a valid move assignment operator, then why can't we move assign it?"); - } + static_assert( + !std::is_move_assignable::value, + "If T has a valid move assignment operator, then why can't we move assign it?"); + } }; - static const int c_nDefaultValue = 123; static const int c_nNonDefaultValue = 456; static_assert(c_nDefaultValue != c_nNonDefaultValue, "If you break this, then these tests are pretty useless"); @@ -51,199 +50,198 @@ static int s_nGlobal = c_nDefaultValue; void SetTestGlobal(int value) noexcept { - s_nGlobal = value; + s_nGlobal = value; } int GetTestGlobal() noexcept { - return s_nGlobal; + return s_nGlobal; } // Hungarian: tr using TestRestorer = Mso::TPropertyRestorer; -TEST_CLASS(TPropertyRestorerTest) +TEST_CLASS (TPropertyRestorerTest) { - TEST_METHOD_INITIALIZE(Setup) - { - SetTestGlobal(c_nDefaultValue); // Ensure every test starts with default global value - } + TEST_METHOD_INITIALIZE(Setup) + { + SetTestGlobal(c_nDefaultValue); // Ensure every test starts with default global value + } - TEST_METHOD(DefaultConstructor_GlobalIsReverted) - { - // Arrange & Act - { - TestRestorer tr; - TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should not be updated"); + TEST_METHOD(DefaultConstructor_GlobalIsReverted) + { + // Arrange & Act + { + TestRestorer tr; + TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should not be updated"); - SetTestGlobal(c_nNonDefaultValue); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - } + SetTestGlobal(c_nNonDefaultValue); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + } - // Assert - TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should be reverted"); - } + // Assert + TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should be reverted"); + } - TEST_METHOD(ConstructorDestructor_Nested_GlobalIsUpdated) - { - // Arrange & Act - { - TestRestorer tr(c_nNonDefaultValue); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + TEST_METHOD(ConstructorDestructor_Nested_GlobalIsUpdated) + { + // Arrange & Act + { + TestRestorer tr(c_nNonDefaultValue); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - { - TestRestorer tr2(123456789); - TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be updated"); - } + { + TestRestorer tr2(123456789); + TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be updated"); + } - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be reverted"); - } + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be reverted"); + } - // Assert - TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should be reverted"); - } + // Assert + TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should be reverted"); + } - TEST_METHOD(Disable_OriginallyEnabled_NotReverted) - { - // Arrange & Act - { - TestRestorer tr(c_nNonDefaultValue); + TEST_METHOD(Disable_OriginallyEnabled_NotReverted) + { + // Arrange & Act + { + TestRestorer tr(c_nNonDefaultValue); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - TestAssert::IsTrue(tr.IsEnabled()); - tr.Disable(); - TestAssert::IsFalse(tr.IsEnabled()); - } + TestAssert::IsTrue(tr.IsEnabled()); + tr.Disable(); + TestAssert::IsFalse(tr.IsEnabled()); + } - // Assert - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted"); - } + // Assert + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted"); + } - TEST_METHOD(MoveOperator_OriginallyEnabled_OriginalIsDisabled) - { - // Arrange & Act - { - TestRestorer tr(c_nNonDefaultValue); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + TEST_METHOD(MoveOperator_OriginallyEnabled_OriginalIsDisabled) + { + // Arrange & Act + { + TestRestorer tr(c_nNonDefaultValue); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - { - TestRestorer tr2(123456789); - TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be updated"); + { + TestRestorer tr2(123456789); + TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be updated"); - TestAssert::IsTrue(tr2.IsEnabled()); - tr = std::move(tr2); - TestAssert::IsFalse(tr2.IsEnabled()); - } + TestAssert::IsTrue(tr2.IsEnabled()); + tr = std::move(tr2); + TestAssert::IsFalse(tr2.IsEnabled()); + } - TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should not be reverted"); - } + TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should not be reverted"); + } - // Assert - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be reverted to tr2's previous value"); - } + // Assert + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be reverted to tr2's previous value"); + } - TEST_METHOD(MoveConstructor_OriginallyEnabled_OriginalIsDisabled) - { - // Arrange & Act - { - TestRestorer tr(std::move(TrSetGlobalToNonDefault())); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - } + TEST_METHOD(MoveConstructor_OriginallyEnabled_OriginalIsDisabled) + { + // Arrange & Act + { + TestRestorer tr(std::move(TrSetGlobalToNonDefault())); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + } - // Assert - TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should be reverted"); - } + // Assert + TestAssert::AreEqual(c_nDefaultValue, GetTestGlobal(), L"Global should be reverted"); + } - TEST_METHOD(MoveConstructor_SetRestoreTo123456789_RestoreTo123456789) - { - // Arrange & Act - { - TestRestorer tr(std::move(TrSetGlobalToNonDefaultAndRestoreTo123456789())); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - } + TEST_METHOD(MoveConstructor_SetRestoreTo123456789_RestoreTo123456789) + { + // Arrange & Act + { + TestRestorer tr(std::move(TrSetGlobalToNonDefaultAndRestoreTo123456789())); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + } - // Assert - TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be reverted"); - } + // Assert + TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be reverted"); + } - TEST_METHOD(SetValueToRestore_SetRestoreTo123456789_RestoreTo123456789) - { - // Arrange & Act - { - TestRestorer tr(c_nNonDefaultValue); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + TEST_METHOD(SetValueToRestore_SetRestoreTo123456789_RestoreTo123456789) + { + // Arrange & Act + { + TestRestorer tr(c_nNonDefaultValue); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - TestAssert::AreEqual(c_nDefaultValue, tr.ValueToRestore()); - tr.ValueToRestore() = 123456789; - TestAssert::AreEqual(123456789, tr.ValueToRestore()); + TestAssert::AreEqual(c_nDefaultValue, tr.ValueToRestore()); + tr.ValueToRestore() = 123456789; + TestAssert::AreEqual(123456789, tr.ValueToRestore()); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted yet"); - } + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted yet"); + } - // Assert - TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be reverted"); - } + // Assert + TestAssert::AreEqual(123456789, GetTestGlobal(), L"Global should be reverted"); + } - TEST_METHOD(ComplexTemplatedTypes_Compiles) - { - struct Unmovable final - { - Unmovable() = default; - private: - Unmovable(Unmovable&&) = delete; - Unmovable& operator=(Unmovable&&) = delete; - DECLARE_COPYCONSTR_AND_ASSIGNMENT(Unmovable); // No copying! - }; + TEST_METHOD(ComplexTemplatedTypes_Compiles) + { + struct Unmovable final + { + Unmovable() = default; - // Ensure PropertyRestorer doesn't cause any extra constructor calls. - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); + private: + Unmovable(Unmovable&&) = delete; + Unmovable& operator=(Unmovable&&) = delete; + DECLARE_COPYCONSTR_AND_ASSIGNMENT(Unmovable); // No copying! + }; - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); - TestProperty::VerifyRestorerCompiles(); + // Ensure PropertyRestorer doesn't cause any extra constructor calls. + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); - TestProperty>::VerifyRestorerCompiles(); - TestProperty&>::VerifyRestorerCompiles(); - TestProperty&&>::VerifyRestorerCompiles(); - TestProperty&>::VerifyRestorerCompiles(); - } + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); + TestProperty::VerifyRestorerCompiles(); + + TestProperty>::VerifyRestorerCompiles(); + TestProperty&>::VerifyRestorerCompiles(); + TestProperty&&>::VerifyRestorerCompiles(); + TestProperty&>::VerifyRestorerCompiles(); + } private: - // any helper type methods + // any helper type methods - static TestRestorer TrSetGlobalToNonDefault() - { - TestAssert::AreNotEqual(c_nNonDefaultValue, GetTestGlobal(), L"This test is less useful if the global already is c_nNonDefaultValue"); + static TestRestorer TrSetGlobalToNonDefault() + { + TestAssert::AreNotEqual( + c_nNonDefaultValue, GetTestGlobal(), L"This test is less useful if the global already is c_nNonDefaultValue"); - auto verifyPostCondition = Mso::TCleanup::Make([]() - { - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted"); - }); + auto verifyPostCondition = Mso::TCleanup::Make( + []() { TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted"); }); - TestRestorer tr(c_nNonDefaultValue); - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); + TestRestorer tr(c_nNonDefaultValue); + TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should be updated"); - return tr; - } + return tr; + } - static TestRestorer TrSetGlobalToNonDefaultAndRestoreTo123456789() - { - TestAssert::AreNotEqual(c_nNonDefaultValue, GetTestGlobal(), L"This test is less useful if the global already is c_nNonDefaultValue"); - TestAssert::AreNotEqual(123456789, GetTestGlobal(), L"This test is less useful if the global already is 123456789"); + static TestRestorer TrSetGlobalToNonDefaultAndRestoreTo123456789() + { + TestAssert::AreNotEqual( + c_nNonDefaultValue, GetTestGlobal(), L"This test is less useful if the global already is c_nNonDefaultValue"); + TestAssert::AreNotEqual(123456789, GetTestGlobal(), L"This test is less useful if the global already is 123456789"); - SetTestGlobal(123456789); + SetTestGlobal(123456789); - auto verifyPostCondition = Mso::TCleanup::Make([]() - { - TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted"); - }); + auto verifyPostCondition = Mso::TCleanup::Make( + []() { TestAssert::AreEqual(c_nNonDefaultValue, GetTestGlobal(), L"Global should not be reverted"); }); - return TrSetGlobalToNonDefault(); - } + return TrSetGlobalToNonDefault(); + } }; diff --git a/libs/cppExtensions/tests/stringLiteralTest.cpp b/libs/cppExtensions/tests/stringLiteralTest.cpp index 9b197cc..e3cc60e 100644 --- a/libs/cppExtensions/tests/stringLiteralTest.cpp +++ b/libs/cppExtensions/tests/stringLiteralTest.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Basic testing for StringLiteral classes + Basic testing for StringLiteral classes */ #include #include @@ -11,66 +11,65 @@ #include using namespace Mso::StringLiterals; -template +template static void CheckLength(size_t expected, const StringLiteral& s) { - TestAssert::AreEqual(expected, std::char_traits::length(s)); + TestAssert::AreEqual(expected, std::char_traits::length(s)); } -TEST_CLASS(StringLiteralTests) +TEST_CLASS (StringLiteralTests) { - static void ConstLengths() noexcept - { - static_assert(""_S.length() == 0, "Invalid compile-time length"); - static_assert("Test"_S.length() == 4, "Invalid compile-time length"); - } + static void ConstLengths() noexcept + { + static_assert(""_S.length() == 0, "Invalid compile-time length"); + static_assert("Test"_S.length() == 4, "Invalid compile-time length"); + } - TEST_METHOD(TestEmpty) - { - CheckLength(0, ""_S); - CheckLength(0, L""_S); - CheckLength(0, u""_S); - CheckLength(0, U""_S); - } + TEST_METHOD(TestEmpty) + { + CheckLength(0, ""_S); + CheckLength(0, L""_S); + CheckLength(0, u""_S); + CheckLength(0, U""_S); + } - TEST_METHOD(TestNonEmpty) - { - CheckLength(3, "Yes"_S); - CheckLength(3, L"Yes"_S); - CheckLength(3, u"Yes"_S); - CheckLength(3, U"Yes"_S); - } + TEST_METHOD(TestNonEmpty) + { + CheckLength(3, "Yes"_S); + CheckLength(3, L"Yes"_S); + CheckLength(3, u"Yes"_S); + CheckLength(3, U"Yes"_S); + } }; -TEST_CLASS(StringLiteralArrayTests) +TEST_CLASS (StringLiteralArrayTests) { - struct HoldString - { - template - constexpr HoldString(const std::array, Count>& strings) noexcept : - m_strings(&strings[0]), - m_count(Count) - { - static_assert(Count != 0, "Must pass at least 1 string"); - - } - - const char* const* m_strings; - const size_t m_count; - }; - - TEST_METHOD(TestArray) - { - static const std::array, 3> strings = - { - "Hi"_S, "This"_S, "Works"_S, - }; - - const HoldString hold(strings); - - //static_assert(hold.m_count == 3, "Incorrect count"); Look at this later - TestAssert::AreEqual("Hi", hold.m_strings[0]); - TestAssert::AreEqual("This", hold.m_strings[1]); - TestAssert::AreEqual("Works", hold.m_strings[2]); - } + struct HoldString + { + template + constexpr HoldString(const std::array, Count>& strings) noexcept + : m_strings(&strings[0]), m_count(Count) + { + static_assert(Count != 0, "Must pass at least 1 string"); + } + + const char* const* m_strings; + const size_t m_count; + }; + + TEST_METHOD(TestArray) + { + static const std::array, 3> strings = { + "Hi"_S, + "This"_S, + "Works"_S, + }; + + const HoldString hold(strings); + + // static_assert(hold.m_count == 3, "Incorrect count"); Look at this later + TestAssert::AreEqual("Hi", hold.m_strings[0]); + TestAssert::AreEqual("This", hold.m_strings[1]); + TestAssert::AreEqual("Works", hold.m_strings[2]); + } }; \ No newline at end of file diff --git a/libs/cppExtensions/tests/testMain.cpp b/libs/cppExtensions/tests/testMain.cpp index fb96396..399ab49 100644 --- a/libs/cppExtensions/tests/testMain.cpp +++ b/libs/cppExtensions/tests/testMain.cpp @@ -4,4 +4,3 @@ #include ImplementTestModule(); - diff --git a/libs/cppType/include/cppType/functionTypeTraits.h b/libs/cppType/include/cppType/functionTypeTraits.h index bbc4b87..a5e6a18 100644 --- a/libs/cppType/include/cppType/functionTypeTraits.h +++ b/libs/cppType/include/cppType/functionTypeTraits.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Various C++ helpers for working with function types + Various C++ helpers for working with function types */ #pragma once #ifndef LIBLET_CPPTYPE_FUNCTIONTYPETRAITS_H @@ -11,94 +11,91 @@ #include #include -namespace Mso -{ +namespace Mso { /** - Turns a function pointer or method pointer type into a normal function type. - Error otherwise. + Turns a function pointer or method pointer type into a normal function type. + Error otherwise. - Note: does not strip volatile/const qualifiers on the pointer. + Note: does not strip volatile/const qualifiers on the pointer. - Note: std::remove_reference is used instead of std::common_type - because of a bug in the STL that causes common_type to not return the - identity with function types. + Note: std::remove_reference is used instead of std::common_type + because of a bug in the STL that causes common_type to not return the + identity with function types. */ template struct fnptr_to_fn; // Handle a member function pointer that is non-const -template -struct fnptr_to_fn +template +struct fnptr_to_fn { - typedef typename std::remove_reference::type type; + typedef typename std::remove_reference::type type; }; // Handle a pointer to a const member function -template -struct fnptr_to_fn +template +struct fnptr_to_fn { - typedef typename std::remove_reference::type type; + typedef typename std::remove_reference::type type; }; // Handle a pointer to a function -template -struct fnptr_to_fn +template +struct fnptr_to_fn { - typedef typename std::remove_reference::type type; + typedef typename std::remove_reference::type type; }; #if defined(__cpp_noexcept_function_type) || (_HAS_NOEXCEPT_FUNCTION_TYPES == 1) // Handle a noexcept member function pointer that is non-const -template -struct fnptr_to_fn +template +struct fnptr_to_fn { - typedef typename std::remove_reference::type type; + typedef typename std::remove_reference::type type; }; // Handle a pointer to a const noexcept member function -template -struct fnptr_to_fn +template +struct fnptr_to_fn { - typedef typename std::remove_reference::type type; + typedef typename std::remove_reference::type type; }; // Handle a pointer to a noexcept function -template -struct fnptr_to_fn +template +struct fnptr_to_fn { - typedef typename std::remove_reference::type type; + typedef typename std::remove_reference::type type; }; #endif - /** - Checks types of two function types to ensure that it is safe to replace the - first [From] function's invocation with the second [To]. + Checks types of two function types to ensure that it is safe to replace the + first [From] function's invocation with the second [To]. - Guaranteed to work if both From and To are function types. - Error otherwise. + Guaranteed to work if both From and To are function types. + Error otherwise. - i.e.: (struct A {}; struct B : A {};) - void() -> void() // good - void(int) -> void(void*) // bad - void(B*) -> void(A*) // good because a B* can always be converted to an A* - A*() -> B*() // good because the same reason as the previous - void(int, double) -> void(int) // bad because parameter count mismatch + i.e.: (struct A {}; struct B : A {};) + void() -> void() // good + void(int) -> void(void*) // bad + void(B*) -> void(A*) // good because a B* can always be converted to an A* + A*() -> B*() // good because the same reason as the previous + void(int, double) -> void(int) // bad because parameter count mismatch - The helper class uses a std::tuple to pack lists of arguments to recurse on. - This is because recursing using function templates causes and ICE on this version - of the compiler. Dev + The helper class uses a std::tuple to pack lists of arguments to recurse on. + This is because recursing using function templates causes and ICE on this version + of the compiler. Dev */ template struct are_function_types_convertible; -namespace details -{ +namespace details { template struct are_function_types_convertible_arguments_helper; @@ -107,53 +104,51 @@ struct are_function_types_convertible_arguments_helper; template <> struct are_function_types_convertible_arguments_helper, std::tuple<>> { - static bool const value = true; + static bool const value = true; }; // base case - false - too many arguments in From. -template -struct are_function_types_convertible_arguments_helper< - std::tuple, - std::tuple<>> +template +struct are_function_types_convertible_arguments_helper, std::tuple<>> { - static const bool value = false; + static const bool value = false; }; // base case - false - too many arguments in To. -template -struct are_function_types_convertible_arguments_helper< - std::tuple<>, - std::tuple> +template +struct are_function_types_convertible_arguments_helper, std::tuple> { - static const bool value = false; + static const bool value = false; }; // recursive step - valid if the head arguments are compatible and the recursive check on the tails are compatible. -template +template < + typename FromArgumentsHead, + typename... FromArgumentsTail, + typename ToArgumentsHead, + typename... ToArgumentsTail> struct are_function_types_convertible_arguments_helper< - std::tuple, - std::tuple> + std::tuple, + std::tuple> { - static const bool value = - std::is_convertible::value && - are_function_types_convertible_arguments_helper, std::tuple>::value; + static const bool value = std::is_convertible::value + && are_function_types_convertible_arguments_helper< + std::tuple, + std::tuple>::value; }; -} +} // namespace details // entry point - matches two function types passed in. -template -struct are_function_types_convertible +template +struct are_function_types_convertible { - static const bool value = - std::is_convertible::value && - details::are_function_types_convertible_arguments_helper< - std::tuple, - std::tuple - >::value; + static const bool value = std::is_convertible::value + && details::are_function_types_convertible_arguments_helper< + std::tuple, + std::tuple>::value; }; } // namespace Mso - #endif // LIBLET_CPPTYPE_FUNCTIONTYPETRAITS_H diff --git a/libs/cppType/include/cppType/restrictHelper.h b/libs/cppType/include/cppType/restrictHelper.h index 42fa32e..515b412 100644 --- a/libs/cppType/include/cppType/restrictHelper.h +++ b/libs/cppType/include/cppType/restrictHelper.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - A collection of functions to help with restricting the behavior of + A collection of functions to help with restricting the behavior of C++ templates based on properties of template parameters. Search the Interweb for "SFINAE" if you want to understand how this works. */ @@ -28,12 +28,16 @@ * * @see MSO_ENABLE_FUNC_IF for enabling a function overload based on a compile-time constraint */ -#define MSO_ENABLE_CLASS_IF( ... ) typename std::enable_if< __VA_ARGS__ >::type - +#define MSO_ENABLE_CLASS_IF(...) typename std::enable_if<__VA_ARGS__>::type // The Mso::Enabled enumeration is part of the `MSO_ENABLE_FUNC_IF` SFINAE magic. // @see MSO_ENABLE_FUNC_IF -namespace Mso { enum class Enabled { _ }; } +namespace Mso { +enum class Enabled +{ + _ +}; +} /** * The `MSO_ENABLE_FUNC_IF` macro allows a function template to apply only when a certain compile-time constraint is @@ -63,26 +67,23 @@ namespace Mso { enum class Enabled { _ }; } * * @see MSO_ENABLE_CLASS_IF for enabling a partial specialization of a class template based on a compile-time constraint */ -#define MSO_ENABLE_FUNC_IF( ... ) typename std::enable_if< __VA_ARGS__, ::Mso::Enabled >::type = ::Mso::Enabled::_ - +#define MSO_ENABLE_FUNC_IF(...) typename std::enable_if<__VA_ARGS__, ::Mso::Enabled>::type = ::Mso::Enabled::_ // Helper macro for constraining function templates to only match certain types via the SFINAE pattern. // Append this macro as the last item in a function template's template parameter list in order to disable // that function template when FROM is not implicitly convertible to TO (note that if what you want is to mimic the // implicit conversion rules for raw pointers, you'll need to specify FROM and TO as pointer types in the macro // invocation, like: MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE( X*, Y* ) -#define MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE( FROM, TO ) \ - typename Enable = typename std::enable_if< std::is_convertible< FROM, TO >::value >::type - +#define MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE(FROM, TO) \ + typename Enable = typename std::enable_if::value>::type // Macro for stamping out embedded typedefs for TYPE. // // This is primarily intended to be invoked within the body of a "smart pointer" class definition, and used in // conjunction with the MSO_IMPLICIT_CONVERSION_[FROM|TO] macros, below. -#define MSO_SMART_POINTER_TYPEDEFS( TYPE ) \ - typedef TYPE ValueType; \ - typedef ValueType* PointerType; - +#define MSO_SMART_POINTER_TYPEDEFS(TYPE) \ + typedef TYPE ValueType; \ + typedef ValueType* PointerType; // Helper macros for constraining smart pointer conversions to mimic builtin ptr implicit conversion rules. Use these // with constructor, assignment operator, or cast operators that are implemented as function templates, in order to @@ -98,9 +99,8 @@ namespace Mso { enum class Enabled { _ }; } // // Use MSO_IMPLICIT_CONVERSION_TO when implementing a cast operator, and MSO_IMPLICIT_CONVERSION_FROM when implementing // a converting constructor or assignment operator. -#define MSO_IMPLICIT_CONVERSION_FROM( TYPE ) TYPE, MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE( TYPE*, PointerType ) -#define MSO_IMPLICIT_CONVERSION_TO( TYPE ) TYPE, MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE( PointerType, TYPE* ) - +#define MSO_IMPLICIT_CONVERSION_FROM(TYPE) TYPE, MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE(TYPE*, PointerType) +#define MSO_IMPLICIT_CONVERSION_TO(TYPE) TYPE, MSO_ENABLE_IF_IMPLICITLY_CONVERTIBLE(PointerType, TYPE*) #endif // __cplusplus diff --git a/libs/cppType/include/cppType/typeTraits.h b/libs/cppType/include/cppType/typeTraits.h index a2bc839..0cb87b1 100644 --- a/libs/cppType/include/cppType/typeTraits.h +++ b/libs/cppType/include/cppType/typeTraits.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Various C++ templates to help with compile-time type information. + Various C++ templates to help with compile-time type information. */ #pragma once #ifndef LIBLET_CPPTYPE_TYPETRAITS_H @@ -15,179 +15,254 @@ namespace Mso { /** - Empty type used for terminating typelists and other places where - a concept of 'no type' is needed. - Note that 'no type' is different than 'void'. + Empty type used for terminating typelists and other places where + a concept of 'no type' is needed. + Note that 'no type' is different than 'void'. */ class NilType { }; /** - Type2Type< T > - Can be used to overload functions which otherwise would differ only by Return type. - e.g. - Since following is not allowed, - Window* Create(); - Scrollbar* Create(); + Type2Type< T > + Can be used to overload functions which otherwise would differ only by Return type. + e.g. + Since following is not allowed, + Window* Create(); + Scrollbar* Create(); - Use: - Window* Create( const Type2Type< Window >& ); - Scrollbar* Create( const Type2Type< Scrollbar >& ); + Use: + Window* Create( const Type2Type< Window >& ); + Scrollbar* Create( const Type2Type< Scrollbar >& ); */ -template< typename T > +template struct Type2Type { - typedef T OriginalType; + typedef T OriginalType; }; /** - RawTraits can be used in templates that support pointer and non-pointer - types to retrieve const and non-const versions. + RawTraits can be used in templates that support pointer and non-pointer + types to retrieve const and non-const versions. - T = wchar_t, RawTraits< T >::ArrowType = wchar_t - T = wchar_t, RawTraits< T >::AddrType = wchar_t* + T = wchar_t, RawTraits< T >::ArrowType = wchar_t + T = wchar_t, RawTraits< T >::AddrType = wchar_t* - T = wchar_t&, RawTraits< T >::ArrowType = wchar_t* - T = wchar_t&, RawTraits< T >::AddrType = wchar_t* + T = wchar_t&, RawTraits< T >::ArrowType = wchar_t* + T = wchar_t&, RawTraits< T >::AddrType = wchar_t* - T = wchar_t*, RawTraits< T >::ArrowType = wchar_t* - T = wchar_t*, RawTraits< T >::AddrType = wchar_t** + T = wchar_t*, RawTraits< T >::ArrowType = wchar_t* + T = wchar_t*, RawTraits< T >::AddrType = wchar_t** - T = const wchar_t*, RawTraits< T >::ArrowType = const wchar_t* - T = const wchar_t*, RawTraits< T >::AddrType = const wchar_t** + T = const wchar_t*, RawTraits< T >::ArrowType = const wchar_t* + T = const wchar_t*, RawTraits< T >::AddrType = const wchar_t** */ -template< typename T > +template class RawTraits - { +{ public: - using ArrowType = T; - using AddrType = T*; + using ArrowType = T; + using AddrType = T*; - static T& GetArrowType(T& t) noexcept { return t; } - enum R { isPointer = false, isReference = false }; - }; + static T& GetArrowType(T& t) noexcept + { + return t; + } + enum R + { + isPointer = false, + isReference = false + }; +}; -template< typename T > -class RawTraits< T& > - { +template +class RawTraits +{ public: - using ArrowType = T*; - using AddrType = T*; + using ArrowType = T*; + using AddrType = T*; - static T* GetArrowType(T& t) noexcept { return &t; } - enum R { isPointer = false, isReference = true }; - }; + static T* GetArrowType(T& t) noexcept + { + return &t; + } + enum R + { + isPointer = false, + isReference = true + }; +}; -template< typename T > -class RawTraits< T* > - { +template +class RawTraits +{ public: - using ArrowType = T*; - using AddrType = T**; + using ArrowType = T*; + using AddrType = T**; - static ArrowType GetArrowType(T* t) noexcept { return t; } - enum R { isPointer = true, isReference = false }; - }; + static ArrowType GetArrowType(T* t) noexcept + { + return t; + } + enum R + { + isPointer = true, + isReference = false + }; +}; /** - EmptyTraits provides methods to deal with whether variables are 'empty'. + EmptyTraits provides methods to deal with whether variables are 'empty'. */ /** - EmptyTraits to use with simple value types + EmptyTraits to use with simple value types */ -template< typename T > +template struct EmptyTraits - { - static T EmptyVal() noexcept { return T(); } - static bool IsEmpty(const T& t) noexcept { return (t == EmptyVal()); } - static void Empty(T& t) noexcept { t = EmptyVal(); } - DECLSPEC_DEPRECATED static void UnsafeEmpty(T& t) noexcept { Empty(t); } - }; +{ + static T EmptyVal() noexcept + { + return T(); + } + static bool IsEmpty(const T& t) noexcept + { + return (t == EmptyVal()); + } + static void Empty(T& t) noexcept + { + t = EmptyVal(); + } + DECLSPEC_DEPRECATED static void UnsafeEmpty(T& t) noexcept + { + Empty(t); + } +}; /** - EmptyTraits to use with pointer types + EmptyTraits to use with pointer types */ -template< typename T > +template struct EmptyTraits - { - static T* EmptyVal() noexcept { return nullptr; } - static bool IsEmpty(std::add_const_t* t) noexcept { return (t == EmptyVal()); } - static void Empty(T*& t) noexcept { t = EmptyVal(); } - DECLSPEC_DEPRECATED static void UnsafeEmpty(T*& t) noexcept { Empty(t); } - }; +{ + static T* EmptyVal() noexcept + { + return nullptr; + } + static bool IsEmpty(std::add_const_t* t) noexcept + { + return (t == EmptyVal()); + } + static void Empty(T*& t) noexcept + { + t = EmptyVal(); + } + DECLSPEC_DEPRECATED static void UnsafeEmpty(T*& t) noexcept + { + Empty(t); + } +}; /** - EmptyTraits to use with reference types + EmptyTraits to use with reference types */ -template< typename T > -struct EmptyTraits< T& > - { - // EmptyVal is explicitly not present - static bool IsEmpty(const T& /*t*/) noexcept { return false; } - // Empty is explicitly not present - DECLSPEC_DEPRECATED static void UnsafeEmpty(T& /*t*/) noexcept {} // Can't empty a reference - }; +template +struct EmptyTraits +{ + // EmptyVal is explicitly not present + static bool IsEmpty(const T& /*t*/) noexcept + { + return false; + } + // Empty is explicitly not present + DECLSPEC_DEPRECATED static void UnsafeEmpty(T& /*t*/) noexcept {} // Can't empty a reference +}; /** - Custom EmptyTraits to use with non-zero defaults, TEmptyVal must be a constant + Custom EmptyTraits to use with non-zero defaults, TEmptyVal must be a constant */ -template< typename T, T TEmptyVal > +template struct CustomEmptyTraits - { - static T EmptyVal() noexcept { return TEmptyVal; } - static bool IsEmpty(const T& t) noexcept { return (t == EmptyVal()); } - static void Empty(T& t) noexcept { t = EmptyVal(); } - DECLSPEC_DEPRECATED static void UnsafeEmpty(T& t) noexcept { Empty(t); } - }; +{ + static T EmptyVal() noexcept + { + return TEmptyVal; + } + static bool IsEmpty(const T& t) noexcept + { + return (t == EmptyVal()); + } + static void Empty(T& t) noexcept + { + t = EmptyVal(); + } + DECLSPEC_DEPRECATED static void UnsafeEmpty(T& t) noexcept + { + Empty(t); + } +}; /** - Custom EmptyTraits to use with zero-init structures like STATSTG + Custom EmptyTraits to use with zero-init structures like STATSTG */ -template< typename T > +template struct PODEmptyTraits - { - static T EmptyVal() noexcept { T t = {0}; return t; } - static bool IsEmpty(const T& t) noexcept { T tEmpty = EmptyVal(); return memcmp(&t, &tEmpty, sizeof(t)) == 0; } - static void Empty(T& t) noexcept { t = EmptyVal(); } - DECLSPEC_DEPRECATED static void UnsafeEmpty(T& t) noexcept { Empty(t); } - }; +{ + static T EmptyVal() noexcept + { + T t = {0}; + return t; + } + static bool IsEmpty(const T& t) noexcept + { + T tEmpty = EmptyVal(); + return memcmp(&t, &tEmpty, sizeof(t)) == 0; + } + static void Empty(T& t) noexcept + { + t = EmptyVal(); + } + DECLSPEC_DEPRECATED static void UnsafeEmpty(T& t) noexcept + { + Empty(t); + } +}; /** - Helper for use with template arguments to force callers to specify type explicitly. + Helper for use with template arguments to force callers to specify type explicitly. - template Bar(const typename Mso::DisableTypeDeduction::type& value) - [...] - Bar(someInt); // compile fails with C2783 - Bar(someInt); // compiles successfully + template Bar(const typename Mso::DisableTypeDeduction::type& value) + [...] + Bar(someInt); // compile fails with C2783 + Bar(someInt); // compiles successfully */ template struct DisableTypeDeduction { - using type = T; + using type = T; }; - /** - OverloadTag can be used be used to disambiguate two function overloads. - OverloadTag instance passed to an overloaded function will give a higher priority to a function accepting - OverloadTagP1 versus function that accepts OverloadTagP2. + OverloadTag can be used be used to disambiguate two function overloads. + OverloadTag instance passed to an overloaded function will give a higher priority to a function accepting + OverloadTagP1 versus function that accepts OverloadTagP2. - For example, we can use it to call a method if it is defined, or do something else if it is not defined. - template auto Foo(Mso::OverloadTagP1, T* x) -> decltype(x->Bar()) { return x->Bar(); } - template int Foo(Mso::OverloadTagP2, T* x) { return DefaultBar(x); } + For example, we can use it to call a method if it is defined, or do something else if it is not defined. + template auto Foo(Mso::OverloadTagP1, T* x) -> decltype(x->Bar()) { return x->Bar(); } + template int Foo(Mso::OverloadTagP2, T* x) { return DefaultBar(x); } - The right function overload will be chosen depending on whether type T has Bar() method or not: - Foo(Mso::OverloadTag(), &x); + The right function overload will be chosen depending on whether type T has Bar() method or not: + Foo(Mso::OverloadTag(), &x); */ using OverloadTagP1 = int; -struct OverloadTagP2 { OverloadTagP2(OverloadTagP1) noexcept {} }; +struct OverloadTagP2 +{ + OverloadTagP2(OverloadTagP1) noexcept {} +}; using OverloadTag = OverloadTagP1; - /** - Identifies the largest type from a variadic set of types. + Identifies the largest type from a variadic set of types. */ template struct LargestType; @@ -195,13 +270,13 @@ struct LargestType; template struct LargestType { - using type = T; + using type = T; }; template struct LargestType { - using type = typename LargestType= sizeof(T2), T1, T2>::type, Ts...>::type; + using type = typename LargestType= sizeof(T2), T1, T2>::type, Ts...>::type; }; } // namespace Mso diff --git a/libs/crash/include/crash/verifyElseCrash.h b/libs/crash/include/crash/verifyElseCrash.h index 93494eb..d9b9876 100644 --- a/libs/crash/include/crash/verifyElseCrash.h +++ b/libs/crash/include/crash/verifyElseCrash.h @@ -18,29 +18,19 @@ DECLSPEC_NORETURN void CrashWithRecovery(uint32_t tag) noexcept; // Asserts first so the dev can easily attach. If already attached, it does not assert // because bringing up the assert dialog can cause more code to run (OM:278842). -#define VerifyElseCrashSzTag(f, sz, tag) \ - Statement( \ - if (!(f)) \ - { \ - AssertSz1Tag(DisableVecAssert(), "Fatal error: %s", (sz), (tag)); \ - CrashWithRecovery(tag); \ - } \ - ) +#define VerifyElseCrashSzTag(f, sz, tag) \ + Statement(if (!(f)) { \ + AssertSz1Tag(DisableVecAssert(), "Fatal error: %s", (sz), (tag)); \ + CrashWithRecovery(tag); \ + }) -#define VerifySucceededElseCrashTag(hr, tag) \ - Statement( \ - const HRESULT _vec_hr_ = (hr); \ - if (FAILED(_vec_hr_)) \ - { \ - AssertSzTag(DisableVecAssert(), "Failed: " #hr, tag); \ - CrashWithRecovery(/*static_cast(_vec_hr_), */tag); \ - }) +#define VerifySucceededElseCrashTag(hr, tag) \ + Statement(const HRESULT _vec_hr_ = (hr); if (FAILED(_vec_hr_)) { \ + AssertSzTag(DisableVecAssert(), "Failed: " #hr, tag); \ + CrashWithRecovery(/*static_cast(_vec_hr_), */ tag); \ + }) -#define VerifyAllocElseCrashTag(ptr, tag) \ - Statement( \ - if (!(ptr)) \ - CrashWithRecovery(tag); \ - ) +#define VerifyAllocElseCrashTag(ptr, tag) Statement(if (!(ptr)) CrashWithRecovery(tag);) #define CrashWithRecoveryOnOOM() CrashWithRecovery(0) diff --git a/libs/crash/src/crash_min.cpp b/libs/crash/src/crash_min.cpp index 3c92a87..0265e88 100644 --- a/libs/crash/src/crash_min.cpp +++ b/libs/crash/src/crash_min.cpp @@ -11,28 +11,28 @@ void CrashWithRecovery(uint32_t /*tag*/) noexcept { - *((volatile int*)0) = 1; - __builtin_trap(); + *((volatile int*)0) = 1; + __builtin_trap(); } #else int CrashHandler(const EXCEPTION_POINTERS* excPtr, uint32_t tag) noexcept { - excPtr->ExceptionRecord->ExceptionCode = tag; - return EXCEPTION_CONTINUE_SEARCH; + excPtr->ExceptionRecord->ExceptionCode = tag; + return EXCEPTION_CONTINUE_SEARCH; } void CrashWithRecovery(uint32_t tag) noexcept { - __try - { - *((int*)0) = 1; - } - __except (CrashHandler(GetExceptionInformation(), tag)) - { - } - __fastfail(tag); + __try + { + *((int*)0) = 1; + } + __except (CrashHandler(GetExceptionInformation(), tag)) + { + } + __fastfail(tag); } #endif \ No newline at end of file diff --git a/libs/debugAssertApi/include/debugAssertApi/debugAssertApi.h b/libs/debugAssertApi/include/debugAssertApi/debugAssertApi.h index 25ed17f..4290264 100644 --- a/libs/debugAssertApi/include/debugAssertApi/debugAssertApi.h +++ b/libs/debugAssertApi/include/debugAssertApi/debugAssertApi.h @@ -2,13 +2,13 @@ // Licensed under the MIT license. /** - API for debug asserts. Must support C callers + API for debug asserts. Must support C callers */ #pragma once #ifndef LIBLET_DEBUGASSERTAPI_DEBUGASSERTAPI_H #define LIBLET_DEBUGASSERTAPI_DEBUGASSERTAPI_H #ifndef RC_INVOKED -#pragma pack(push,8) +#pragma pack(push, 8) #include #include @@ -22,22 +22,22 @@ Basic debug assert macros to use. Assert: evaluate in debug, call the debug handler on failure AssertDo: always evaluate, call the debug handler on failure */ -#define Assert(f) AssertTag(f, UNTAGGED) -#define AssertSz(f, _sz) AssertSzTag(f, _sz, UNTAGGED) -#define AssertSz0(f, _sz) AssertSzTag(f, _sz, UNTAGGED) -#define AssertSz1(f, _sz, a) AssertSz1Tag(f, _sz, a, UNTAGGED) -#define AssertSz2(f, _sz, a, b) AssertSz2Tag(f, _sz, a, b, UNTAGGED) -#define AssertSz3(f, _sz, a, b, c) AssertSz3Tag(f, _sz, a, b, c, UNTAGGED) -#define AssertSz4(f, _sz, a, b, c, d) AssertSz4Tag(f, _sz, a, b, c, d, UNTAGGED) -#define AssertSz5(f, _sz, a, b, c, d, e) AssertSz5Tag(f, _sz, a, b, c, d, e, UNTAGGED) +#define Assert(f) AssertTag(f, UNTAGGED) +#define AssertSz(f, _sz) AssertSzTag(f, _sz, UNTAGGED) +#define AssertSz0(f, _sz) AssertSzTag(f, _sz, UNTAGGED) +#define AssertSz1(f, _sz, a) AssertSz1Tag(f, _sz, a, UNTAGGED) +#define AssertSz2(f, _sz, a, b) AssertSz2Tag(f, _sz, a, b, UNTAGGED) +#define AssertSz3(f, _sz, a, b, c) AssertSz3Tag(f, _sz, a, b, c, UNTAGGED) +#define AssertSz4(f, _sz, a, b, c, d) AssertSz4Tag(f, _sz, a, b, c, d, UNTAGGED) +#define AssertSz5(f, _sz, a, b, c, d, e) AssertSz5Tag(f, _sz, a, b, c, d, e, UNTAGGED) -#define AssertDo(f) AssertDoTag(f, UNTAGGED) -#define AssertDoSz(f, _sz) AssertDoSzTag(f, _sz, UNTAGGED) -#define AssertDoSz1(f, _sz, a) AssertDoSz1Tag(f, _sz, a, UNTAGGED) -#define AssertDoSz2(f, _sz, a, b) AssertDoSz2Tag(f, _sz, a, b, UNTAGGED) -#define AssertDoSz3(f, _sz, a, b, c) AssertDoSz3Tag(f, _sz, a, b, c, UNTAGGED) -#define AssertDoSz4(f, _sz, a, b, c, d) AssertDoSz4Tag(f, _sz, a, b, c, d, UNTAGGED) -#define AssertDoSz5(f, _sz, a, b, c, d, e) AssertDoSz5Tag(f, _sz, a, b, c, d, e, UNTAGGED) +#define AssertDo(f) AssertDoTag(f, UNTAGGED) +#define AssertDoSz(f, _sz) AssertDoSzTag(f, _sz, UNTAGGED) +#define AssertDoSz1(f, _sz, a) AssertDoSz1Tag(f, _sz, a, UNTAGGED) +#define AssertDoSz2(f, _sz, a, b) AssertDoSz2Tag(f, _sz, a, b, UNTAGGED) +#define AssertDoSz3(f, _sz, a, b, c) AssertDoSz3Tag(f, _sz, a, b, c, UNTAGGED) +#define AssertDoSz4(f, _sz, a, b, c, d) AssertDoSz4Tag(f, _sz, a, b, c, d, UNTAGGED) +#define AssertDoSz5(f, _sz, a, b, c, d, e) AssertDoSz5Tag(f, _sz, a, b, c, d, e, UNTAGGED) /** The following macros can be used to assert inside an expression. @@ -46,39 +46,39 @@ LATER: add more if needed or ShipAssert versions. if (FAssertDo(f)) { ... } // same as "if (f) { ... } else Assert(false);" */ -#define FAssertDo(f) FAssertDoTag(f, UNTAGGED) -#define FAssertDoSz(f, _sz) FAssertDoSzTag(f, _sz, UNTAGGED) -#define FAssertDoSz1(f, _sz, a) FAssertDoSz1Tag(f, _sz, a, UNTAGGED) -#define FAssertDoSz2(f, _sz, a, b) FAssertDoSz2Tag(f, _sz, a, b, UNTAGGED) +#define FAssertDo(f) FAssertDoTag(f, UNTAGGED) +#define FAssertDoSz(f, _sz) FAssertDoSzTag(f, _sz, UNTAGGED) +#define FAssertDoSz1(f, _sz, a) FAssertDoSz1Tag(f, _sz, a, UNTAGGED) +#define FAssertDoSz2(f, _sz, a, b) FAssertDoSz2Tag(f, _sz, a, b, UNTAGGED) #ifdef __cplusplus #define AssertDetails_SzCast(sz) static_cast(sz) #else -#define AssertDetails_SzCast(sz) (const char*) (sz) +#define AssertDetails_SzCast(sz) (const char*)(sz) #endif /** Suppressed warnings in Assert macros: - C4127 - if/while loop condition is a constant - C4018 - signed/unsigned compare was converted to unsigned/unsigned compare - C4389 - operation involved signed/unsigned variables - 6239 - OACR left expression is always false - 25011 - OACR missing 'break' or '__fallthrough' statement - 25037 - OACR expression is always false - 25038 - OACR expression is always false - 25039 - OACR expression is always true - 25041 - OACR if/while loop condition is true - 25042 - OACR if/while loop condition is false - 25064 - OACR function called twice in macro + C4127 - if/while loop condition is a constant + C4018 - signed/unsigned compare was converted to unsigned/unsigned compare + C4389 - operation involved signed/unsigned variables + 6239 - OACR left expression is always false + 25011 - OACR missing 'break' or '__fallthrough' statement + 25037 - OACR expression is always false + 25038 - OACR expression is always false + 25039 - OACR expression is always true + 25041 - OACR if/while loop condition is true + 25042 - OACR if/while loop condition is false + 25064 - OACR function called twice in macro */ -#define AssertDetails_Statement_Begin \ - __pragma(warning(push)) \ - __pragma(warning(disable:4127 4018 4389 6239 25037 25038 25039 25041 25042 25064 25306)) \ - do { +#define AssertDetails_Statement_Begin \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4127 4018 4389 6239 25037 25038 25039 25041 25042 25064 25306)) do \ + { #define AssertDetails_Statement_End \ - } while(0) \ - __pragma(warning(suppress:25011)) \ - __pragma(warning(pop)) \ + } \ + while (0) \ + __pragma(warning(suppress : 25011)) __pragma(warning(pop)) // NOTE: OACR_ASSUME uses the Assert macro, so oacr.h must be included after Assert is defined #include @@ -89,7 +89,7 @@ FUTURE: get rid of this and just use void* */ typedef struct _MSORADDR { - void* pfnCaller; + void* pfnCaller; } MSORADDR; /** @@ -111,7 +111,7 @@ using MsoAssertParamsType = const struct _MsoAssertParams&; #else // __cplusplus typedef struct _MsoAssertParams* MsoAssertParamsType; #ifdef DEBUG -#define DeclareMsoAssertParams(...) (__pragma(warning(suppress:4204)) MsoAssertParams params = { __VA_ARGS__ }) +#define DeclareMsoAssertParams(...) (__pragma(warning(suppress : 4204)) MsoAssertParams params = {__VA_ARGS__}) #else #define DeclareMsoAssertParams(...) #endif // DEBUG @@ -129,50 +129,69 @@ This structure is duplicated in MotifTest project. */ typedef struct _MsoAssertParams { - uint32_t dwTag; - const char* szFile; - uint32_t iLine; - const char* szTitle; - const MSORADDR* rgCallstack; - uint32_t cCallstack; - const char* szCondition; + uint32_t dwTag; + const char* szFile; + uint32_t iLine; + const char* szTitle; + const MSORADDR* rgCallstack; + uint32_t cCallstack; + const char* szCondition; - // Skip this many frames if a callstack is generated. + // Skip this many frames if a callstack is generated. #ifdef __cplusplus - mutable + mutable #endif // __cplusplus - uint32_t framesToSkip; + uint32_t framesToSkip; #ifdef __cplusplus - explicit _MsoAssertParams(uint32_t dwTagLocal = UNTAGGED, - _In_z_ const char* szFileLocal = __FILE__, uint32_t iLineLocal = __LINE__, - _In_opt_z_ const char* szTitleLocal = nullptr, - _In_opt_count_(cCallstackLocal) const MSORADDR* rgCallstackLocal = nullptr, uint32_t cCallstackLocal = 0, - _In_opt_z_ const char* szConditionLocal = "false") MSONOEXCEPT : - dwTag(dwTagLocal), szFile(szFileLocal), iLine(iLineLocal), szTitle(szTitleLocal), - rgCallstack(rgCallstackLocal), cCallstack(cCallstackLocal), - szCondition(szConditionLocal), framesToSkip(0) - { - } + explicit _MsoAssertParams( + uint32_t dwTagLocal = UNTAGGED, + _In_z_ const char* szFileLocal = __FILE__, + uint32_t iLineLocal = __LINE__, + _In_opt_z_ const char* szTitleLocal = nullptr, + _In_opt_count_(cCallstackLocal) const MSORADDR* rgCallstackLocal = nullptr, + uint32_t cCallstackLocal = 0, + _In_opt_z_ const char* szConditionLocal = "false") MSONOEXCEPT + : dwTag(dwTagLocal) + , szFile(szFileLocal) + , iLine(iLineLocal) + , szTitle(szTitleLocal) + , rgCallstack(rgCallstackLocal) + , cCallstack(cCallstackLocal) + , szCondition(szConditionLocal) + , framesToSkip(0) + { + } - explicit _MsoAssertParams(_In_z_ const char* szConditionLocal, uint32_t dwTagLocal, _In_z_ const char* szFileLocal, int32_t iLineLocal) MSONOEXCEPT : - dwTag(dwTagLocal), szFile(szFileLocal), iLine(static_cast(iLineLocal)), szTitle(nullptr), - rgCallstack(nullptr), cCallstack(0), szCondition(szConditionLocal), framesToSkip(0) - { - } + explicit _MsoAssertParams( + _In_z_ const char* szConditionLocal, + uint32_t dwTagLocal, + _In_z_ const char* szFileLocal, + int32_t iLineLocal) MSONOEXCEPT + : dwTag(dwTagLocal) + , szFile(szFileLocal) + , iLine(static_cast(iLineLocal)) + , szTitle(nullptr) + , rgCallstack(nullptr) + , cCallstack(0) + , szCondition(szConditionLocal) + , framesToSkip(0) + { + } #endif // __cplusplus } MsoAssertParams; /** - Function for handling asserts with strings. Return value is AssertResult. - Note: this function has to be callable from C code + Function for handling asserts with strings. Return value is AssertResult. + Note: this function has to be callable from C code */ #if defined(__cplusplus) -extern "C" { +extern "C" +{ #endif // C++ -LIBLET_PUBLICAPI int32_t MsoAssertSzTagProc(MsoAssertParamsType params, _Printf_format_string_ const char* szFmt, va_list argList) MSONOEXCEPT; + LIBLET_PUBLICAPI int32_t + MsoAssertSzTagProc(MsoAssertParamsType params, _Printf_format_string_ const char* szFmt, va_list argList) MSONOEXCEPT; #if defined(__cplusplus) - } #endif // C++ @@ -182,99 +201,95 @@ LIBLET_PUBLICAPI int32_t MsoAssertSzTagProc(MsoAssertParamsType params, _Printf_ #ifdef DEBUG #ifdef __cplusplus -namespace Mso { -namespace DebugAsserts { +namespace Mso { namespace DebugAsserts { -using AssertIgnorer = bool(*)(const MsoAssertParams& params, const char* szMsg); +using AssertIgnorer = bool (*)(const MsoAssertParams& params, const char* szMsg); /** - Add an assert ignorer for this process. - Note: this API is not thread-safe. + Add an assert ignorer for this process. + Note: this API is not thread-safe. */ LIBLET_PUBLICAPI void AddAssertIgnorer(AssertIgnorer ignorer) noexcept; /** - Remove an assert ignorer for this process. - Note: this API is not thread-safe. + Remove an assert ignorer for this process. + Note: this API is not thread-safe. */ LIBLET_PUBLICAPI void RemoveAssertIgnorer(AssertIgnorer ignorer) noexcept; struct AutoRegisterAssertIgnorer { - AutoRegisterAssertIgnorer(AssertIgnorer ignorer) noexcept : m_ignorer(ignorer) - { - AddAssertIgnorer(m_ignorer); - } + AutoRegisterAssertIgnorer(AssertIgnorer ignorer) noexcept : m_ignorer(ignorer) + { + AddAssertIgnorer(m_ignorer); + } - ~AutoRegisterAssertIgnorer() noexcept - { - RemoveAssertIgnorer(m_ignorer); - } + ~AutoRegisterAssertIgnorer() noexcept + { + RemoveAssertIgnorer(m_ignorer); + } private: - AssertIgnorer m_ignorer; + AssertIgnorer m_ignorer; }; -using AssertListener = void(*)(const MsoAssertParams& params, const char* szMsg); +using AssertListener = void (*)(const MsoAssertParams& params, const char* szMsg); /** - Add an assert listener for this process. - Note: this API is not thread-safe. + Add an assert listener for this process. + Note: this API is not thread-safe. */ LIBLET_PUBLICAPI void AddAssertListener(AssertListener listener) noexcept; /** - Remove a previously registered assert listener for this process. - Note: this API is not thread-safe. + Remove a previously registered assert listener for this process. + Note: this API is not thread-safe. */ LIBLET_PUBLICAPI void RemoveAssertListener(AssertListener listener) noexcept; struct AutoRegisterAssertListener { - AutoRegisterAssertListener(AssertListener listener) noexcept : m_listener(listener) - { - AddAssertListener(m_listener); - } + AutoRegisterAssertListener(AssertListener listener) noexcept : m_listener(listener) + { + AddAssertListener(m_listener); + } - ~AutoRegisterAssertListener() noexcept - { - RemoveAssertListener(m_listener); - } + ~AutoRegisterAssertListener() noexcept + { + RemoveAssertListener(m_listener); + } private: - AssertListener m_listener; + AssertListener m_listener; }; -using AssertHandler = int32_t(*)(const MsoAssertParams& params, const char* szMsg); +using AssertHandler = int32_t (*)(const MsoAssertParams& params, const char* szMsg); /** - Set the assert handler for this process. The previous handler is returned. - Note: this API is not thread-safe. + Set the assert handler for this process. The previous handler is returned. + Note: this API is not thread-safe. */ LIBLET_PUBLICAPI AssertHandler SetAssertHandler(AssertHandler handler) noexcept; /** - Get the current assert handler for this process. + Get the current assert handler for this process. */ LIBLET_PUBLICAPI AssertHandler GetAssertHandler() noexcept; struct AutoRegisterAssertHandler { - AutoRegisterAssertHandler(AssertHandler handler) noexcept : m_previous(SetAssertHandler(handler)) - { - } + AutoRegisterAssertHandler(AssertHandler handler) noexcept : m_previous(SetAssertHandler(handler)) {} - ~AutoRegisterAssertHandler() noexcept - { - SetAssertHandler(m_previous); - } + ~AutoRegisterAssertHandler() noexcept + { + SetAssertHandler(m_previous); + } private: - AssertHandler m_previous; + AssertHandler m_previous; }; -} // DebugAsserts -} // Mso +}} // namespace Mso::DebugAsserts #endif // __cplusplus #endif // DEBUG diff --git a/libs/debugAssertApi/include/debugAssertApi/debugAssertDetails.h b/libs/debugAssertApi/include/debugAssertApi/debugAssertDetails.h index a1e5ed3..13e6ce8 100644 --- a/libs/debugAssertApi/include/debugAssertApi/debugAssertDetails.h +++ b/libs/debugAssertApi/include/debugAssertApi/debugAssertDetails.h @@ -2,11 +2,11 @@ // Licensed under the MIT license. /** - Private implementation details for debug assert macros - This header should not be included directly - only through debugAssertApi.h + Private implementation details for debug assert macros + This header should not be included directly - only through debugAssertApi.h - Note that C4706 is purposely left enabled. Assignments in inside Assert - statements are almost always a bug (e.g. Assert(m_foo = fooBar)) + Note that C4706 is purposely left enabled. Assignments in inside Assert + statements are almost always a bug (e.g. Assert(m_foo = fooBar)) */ #pragma once #ifndef LIBLET_DEBUGASSERTAPI_DEBUGASSERTDETAILS_H @@ -18,19 +18,25 @@ /** Mappings for core Debug asserts. */ -#pragma warning(suppress:4005) // macro redefinition :( -#define AssertTag(f, tag) AssertAnnotatedSzNTagImpl(f, L## #f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), "%s", #f) -#define AssertSzTag(f, sz, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), "%s", AssertDetails_SzCast(sz)) -#define AssertSz1Tag(f, sz, a, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a) -#define AssertSz2Tag(f, sz, a, b, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b) -#define AssertSz3Tag(f, sz, a, b, c, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b, c) -#define AssertSz4Tag(f, sz, a, b, c, d, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b, c, d) -#define AssertSz5Tag(f, sz, a, b, c, d, e, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b, c, d, e) +#pragma warning(suppress : 4005) // macro redefinition :( +#define AssertTag(f, tag) \ + AssertAnnotatedSzNTagImpl(f, L## #f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), "%s", #f) +#define AssertSzTag(f, sz, tag) \ + AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), "%s", AssertDetails_SzCast(sz)) +#define AssertSz1Tag(f, sz, a, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a) +#define AssertSz2Tag(f, sz, a, b, tag) AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b) +#define AssertSz3Tag(f, sz, a, b, c, tag) \ + AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b, c) +#define AssertSz4Tag(f, sz, a, b, c, d, tag) \ + AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b, c, d) +#define AssertSz5Tag(f, sz, a, b, c, d, e, tag) \ + AssertSzNTagImpl(f, InlineMsoAssertParams(#f, tag, __FILE__, __LINE__), sz, a, b, c, d, e) -#define FAssertDoTag(f, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L## #f, "%s", #f) -#define FAssertDoSzTag(f, sz, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L##sz, "%s", AssertDetails_SzCast(sz)) -#define FAssertDoSz1Tag(f, sz, a, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L##sz, sz, a) -#define FAssertDoSz2Tag(f, sz, a, b, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L##sz, sz, a, b) +#define FAssertDoTag(f, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L## #f, "%s", #f) +#define FAssertDoSzTag(f, sz, tag) \ + FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L##sz, "%s", AssertDetails_SzCast(sz)) +#define FAssertDoSz1Tag(f, sz, a, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L##sz, sz, a) +#define FAssertDoSz2Tag(f, sz, a, b, tag) FAssertDoSzNTagImpl(f, tag, __FILE__, __LINE__, L##sz, sz, a, b) /** Return values from MsoAssertSzTagProc(Inline)(2) @@ -41,21 +47,18 @@ static const uint32_t c_assertAlwaysIgnore = 2; #ifdef __cplusplus #ifdef DEBUG -namespace Mso { -namespace DebugAsserts { +namespace Mso { namespace DebugAsserts { /** - Return values from MsoAssertSzTagProc(Inline)(2) + Return values from MsoAssertSzTagProc(Inline)(2) */ -__pragma(warning(suppress:4472)) enum class AssertResult : uint32_t -{ - Ignore = c_assertIgnore, - Break = c_assertDebugBreak, - AlwaysIgnore = c_assertAlwaysIgnore, +__pragma(warning(suppress : 4472)) enum class AssertResult : uint32_t { + Ignore = c_assertIgnore, + Break = c_assertDebugBreak, + AlwaysIgnore = c_assertAlwaysIgnore, }; -} // DebugAsserts -} // Mso +}} // namespace Mso::DebugAsserts #endif // DEBUG #endif // C++ @@ -63,58 +66,57 @@ __pragma(warning(suppress:4472)) enum class AssertResult : uint32_t #if defined(__clang__) || defined(__cplusplus_cli) || defined(__INTELLISENSE__) #define AssertBreak(wzMsg) __debugbreak() #elif defined(_DBGRAISEASSERTIONFAILURE_) -#define AssertBreak(wzMsg) \ - (__annotation(L"Debug", L"AssertFail", wzMsg), DbgRaiseAssertionFailure()) +#define AssertBreak(wzMsg) (__annotation(L"Debug", L"AssertFail", wzMsg), DbgRaiseAssertionFailure()) #else -#define AssertBreak(wzMsg) \ - (__annotation(L"Debug", L"AssertFail", wzMsg), __debugbreak()) +#define AssertBreak(wzMsg) (__annotation(L"Debug", L"AssertFail", wzMsg), __debugbreak()) #endif #if DEBUG /** - MsoAssertSzTagProcInline + MsoAssertSzTagProcInline - Converts variable arguments into the arg list format + Converts variable arguments into the arg list format */ #ifndef __cplusplus static #endif -__inline int32_t MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_format_string_ const char* szFmt, ...) MSONOEXCEPT -{ - va_list argList; - va_start(argList, szFmt); - AccessMsoAssertParams(params)->framesToSkip++; - return MsoAssertSzTagProc(params, szFmt, argList); + __inline int32_t + MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_format_string_ const char* szFmt, ...) MSONOEXCEPT +{ + va_list argList; + va_start(argList, szFmt); + AccessMsoAssertParams(params)->framesToSkip++; + return MsoAssertSzTagProc(params, szFmt, argList); } -#ifdef __cplusplus +#ifdef __cplusplus /** - MsoAssertSzTagProcInline2 + MsoAssertSzTagProcInline2 - Converts variable arguments into the arg list format + Converts variable arguments into the arg list format - Use a lamba function to generate a unique function providing storage of - _fIgnore_ (for in-proc based assert management) and unique break address. + Use a lamba function to generate a unique function providing storage of + _fIgnore_ (for in-proc based assert management) and unique break address. */ -#define MsoAssertSzTagProcInline2(dwTag, szFile, iLine, wzAnnotation, szFmt, ...) \ - [&]() -> int32_t { \ - __pragma(warning(suppress:4456)) /* declaration of '_fIgnore_' hides previous local declaration */ \ - static int32_t _fIgnore_ = false; \ - if (!_fIgnore_) \ - { \ - __pragma(warning(suppress:4456)) /* declaration of 'params' hides previous local declaration */ \ - DeclareMsoAssertParams(dwTag, szFile, iLine); \ - params.framesToSkip++; \ - const int32_t _assertResult_ = MsoAssertSzTagProcInline(PassMsoAssertParams(params), szFmt, __VA_ARGS__); \ - __pragma(warning(suppress:4700)) /* MSVC is unhappy with this used in a loop conditional */ \ - if(_assertResult_ == c_assertDebugBreak) \ - { \ - AssertBreak(wzAnnotation); \ - } \ - _fIgnore_ = (_assertResult_ == c_assertAlwaysIgnore); \ - } \ - return FALSE; \ - }() +#define MsoAssertSzTagProcInline2(dwTag, szFile, iLine, wzAnnotation, szFmt, ...) \ + [&]() -> int32_t { \ + __pragma(warning(suppress : 4456)) /* declaration of '_fIgnore_' hides previous local declaration */ \ + static int32_t _fIgnore_ = false; \ + if (!_fIgnore_) \ + { \ + __pragma(warning(suppress : 4456)) /* declaration of 'params' hides previous local declaration */ \ + DeclareMsoAssertParams(dwTag, szFile, iLine); \ + params.framesToSkip++; \ + const int32_t _assertResult_ = MsoAssertSzTagProcInline(PassMsoAssertParams(params), szFmt, __VA_ARGS__); \ + __pragma(warning(suppress : 4700)) /* MSVC is unhappy with this used in a loop conditional */ \ + if (_assertResult_ == c_assertDebugBreak) \ + { \ + AssertBreak(wzAnnotation); \ + } \ + _fIgnore_ = (_assertResult_ == c_assertAlwaysIgnore); \ + } \ + return FALSE; \ + }() #endif // __cplusplus #else @@ -122,7 +124,7 @@ __inline int32_t MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_fo #endif // DEBUG /** - Hide the debug assert 'f' condition from OACR so it acts more like a ship build + Hide the debug assert 'f' condition from OACR so it acts more like a ship build */ #if OACR #define AssertDetails_ShouldRaiseDebugAssert(f, fIgnore) 0 @@ -133,27 +135,25 @@ __inline int32_t MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_fo #if DEBUG /** - AssertSzNTagImpl - all debug asserts funnel into here - TODO: need to move the Ignore logic, should it be on params? - Params is MsoAssertParams, only C callers need to do something weird. + AssertSzNTagImpl - all debug asserts funnel into here + TODO: need to move the Ignore logic, should it be on params? + Params is MsoAssertParams, only C callers need to do something weird. - Note: be aware that ... requires at least one argument + Note: be aware that ... requires at least one argument */ -#define AssertSzNTagImpl(f, params, sz, ...) \ - AssertAnnotatedSzNTagImpl(f, L## #f, params, sz, __VA_ARGS__) +#define AssertSzNTagImpl(f, params, sz, ...) AssertAnnotatedSzNTagImpl(f, L## #f, params, sz, __VA_ARGS__) -#define AssertAnnotatedSzNTagImpl(f, wzAnnotation, params, sz, ...) \ - AssertDetails_Statement_Begin \ - static int32_t _fIgnore_ = 0; \ - if (AssertDetails_ShouldRaiseDebugAssert(f, _fIgnore_)) \ - { \ - DeclareInlineMsoAssertParams(params); \ - const int32_t _assertResult_ = MsoAssertSzTagProcInline(PassMsoAssertParams(params), sz, __VA_ARGS__); \ - if (_assertResult_ == c_assertDebugBreak) \ - AssertBreak(wzAnnotation); \ - _fIgnore_ = (_assertResult_ == c_assertAlwaysIgnore); \ - } \ - AssertDetails_Statement_End +#define AssertAnnotatedSzNTagImpl(f, wzAnnotation, params, sz, ...) \ + AssertDetails_Statement_Begin static int32_t _fIgnore_ = 0; \ + if (AssertDetails_ShouldRaiseDebugAssert(f, _fIgnore_)) \ + { \ + DeclareInlineMsoAssertParams(params); \ + const int32_t _assertResult_ = MsoAssertSzTagProcInline(PassMsoAssertParams(params), sz, __VA_ARGS__); \ + if (_assertResult_ == c_assertDebugBreak) \ + AssertBreak(wzAnnotation); \ + _fIgnore_ = (_assertResult_ == c_assertAlwaysIgnore); \ + } \ + AssertDetails_Statement_End #else @@ -165,15 +165,15 @@ __inline int32_t MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_fo #if DEBUG && !OACR // OACR can't understand FAssertDoSzNTagImpl /** - FAssertDoSzNTagImpl - all debug FAsserts funnel into here - || + FAssertDoSzNTagImpl - all debug FAsserts funnel into here + || - TODO: need to move the Ignore logic, handle these differently? - Note: be aware that ... requires at least one argument + TODO: need to move the Ignore logic, handle these differently? + Note: be aware that ... requires at least one argument */ #define FAssertDoSzNTagImpl(f, dwTag, szFile, iLine, wzAnnotation, sz, ...) \ - ((f) || (MsoAssertSzTagProcInline2(dwTag, szFile, iLine, wzAnnotation, sz, __VA_ARGS__))) + ((f) || (MsoAssertSzTagProcInline2(dwTag, szFile, iLine, wzAnnotation, sz, __VA_ARGS__))) #else @@ -183,40 +183,50 @@ __inline int32_t MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_fo #endif // DEBUG && !OACR // Note: AssertDo may contain assignments so I'm using the != 0 syntax which allows that. -#define AssertDoTag(f, tag) Statement(if ((f) == 0) { AssertSzTag(0, #f, tag); }) -#define AssertDoSzTag(f, sz, tag) Statement(if ((f) == 0) { AssertSzTag(0, sz, tag); }) -#define AssertDoSz1Tag(f, sz, a, tag) Statement(if ((f) == 0) { AssertSz1Tag(0, sz, a, tag); }) -#define AssertDoSz2Tag(f, sz, a, b, tag) Statement(if ((f) == 0) { AssertSz2Tag(0, sz, a, b, tag); }) -#define AssertDoSz3Tag(f, sz, a, b, c, tag) Statement(if ((f) == 0) { AssertSz3Tag(0, sz, a, b, c, tag); }) -#define AssertDoSz4Tag(f, sz, a, b, c, d, tag) Statement(if ((f) == 0) { AssertSz4Tag(0, sz, a, b, c, d, tag); }) -#define AssertDoSz5Tag(f, sz, a, b, c, d, e, tag) Statement(if ((f) == 0) { AssertSz5Tag(0, sz, a, b, c, d, e, tag); }) +#define AssertDoTag(f, tag) Statement(if ((f) == 0) { AssertSzTag(0, #f, tag); }) +#define AssertDoSzTag(f, sz, tag) Statement(if ((f) == 0) { AssertSzTag(0, sz, tag); }) +#define AssertDoSz1Tag(f, sz, a, tag) Statement(if ((f) == 0) { AssertSz1Tag(0, sz, a, tag); }) +#define AssertDoSz2Tag(f, sz, a, b, tag) Statement(if ((f) == 0) { AssertSz2Tag(0, sz, a, b, tag); }) +#define AssertDoSz3Tag(f, sz, a, b, c, tag) Statement(if ((f) == 0) { AssertSz3Tag(0, sz, a, b, c, tag); }) +#define AssertDoSz4Tag(f, sz, a, b, c, d, tag) Statement(if ((f) == 0) { AssertSz4Tag(0, sz, a, b, c, d, tag); }) +#define AssertDoSz5Tag(f, sz, a, b, c, d, e, tag) Statement(if ((f) == 0) { AssertSz5Tag(0, sz, a, b, c, d, e, tag); }) /** - Helpers for debug HRESULT asserts. - - Ship versions are not supported; consider VerifySucceededElseCrash + Helpers for debug HRESULT asserts. + + Ship versions are not supported; consider VerifySucceededElseCrash */ #if DEBUG -#define AssertDoSucceededTag(expr, tag) \ - AssertDetails_Statement_Begin \ - HRESULT _hr_ = (expr); \ - AssertAnnotatedSzNTagImpl(SUCCEEDED(_hr_), L#expr L" success. Check local variable _hr_.", InlineMsoAssertParams("SUCCEEDED(" #expr ")", tag, __FILE__, __LINE__), "%s failed with 0x%08x", #expr, _hr_); \ - AssertDetails_Statement_End +#define AssertDoSucceededTag(expr, tag) \ + AssertDetails_Statement_Begin HRESULT _hr_ = (expr); \ + AssertAnnotatedSzNTagImpl( \ + SUCCEEDED(_hr_), \ + L#expr L" success. Check local variable _hr_.", \ + InlineMsoAssertParams("SUCCEEDED(" #expr ")", tag, __FILE__, __LINE__), \ + "%s failed with 0x%08x", \ + #expr, \ + _hr_); \ + AssertDetails_Statement_End -#define FAssertDoSucceededTag(expr, tag) \ - [&]() noexcept -> bool { \ - HRESULT _hr_ = (expr); \ - if (FAILED(_hr_)) \ - { \ - if (MsoAssertSzTagProcInline(InlineMsoAssertParams("SUCCEEDED(" #expr ")", tag, __FILE__, __LINE__), "%s failed with 0x%08x", #expr, _hr_) == c_assertDebugBreak) \ - { \ - AssertBreak(L#expr L" success. Check local variable _hr_."); \ - } \ - } \ - return SUCCEEDED(_hr_); \ - OACR_WARNING_SUPPRESS( NOEXCEPT_FUNC_THROWS, "Ignore whether expr throws." ); \ - }() \ +#define FAssertDoSucceededTag(expr, tag) \ + [&]() noexcept -> bool { \ + HRESULT _hr_ = (expr); \ + if (FAILED(_hr_)) \ + { \ + if (MsoAssertSzTagProcInline( \ + InlineMsoAssertParams("SUCCEEDED(" #expr ")", tag, __FILE__, __LINE__), \ + "%s failed with 0x%08x", \ + #expr, \ + _hr_) \ + == c_assertDebugBreak) \ + { \ + AssertBreak(L#expr L" success. Check local variable _hr_."); \ + } \ + } \ + return SUCCEEDED(_hr_); \ + OACR_WARNING_SUPPRESS(NOEXCEPT_FUNC_THROWS, "Ignore whether expr throws."); \ + }() #else @@ -226,9 +236,9 @@ __inline int32_t MsoAssertSzTagProcInline(MsoAssertParamsType params, _Printf_fo #endif // DEBUG /** - Random other deprecated assert macros + Random other deprecated assert macros */ -#define AssertImpliesTag(a, b, tag) AssertSzTag(FImplies(a, b), #a " => " #b, tag) -#define AssertBiImpliesTag(a, b, tag) AssertSzTag(FBiImplies(a, b), #a " <==> " #b, tag) +#define AssertImpliesTag(a, b, tag) AssertSzTag(FImplies(a, b), #a " => " #b, tag) +#define AssertBiImpliesTag(a, b, tag) AssertSzTag(FBiImplies(a, b), #a " <==> " #b, tag) #endif // LIBLET_DEBUGASSERTAPI_DEBUGASSERTDETAILS_H diff --git a/libs/debugAssertApi/include/debugAssertApi/debugAssertDisabler.h b/libs/debugAssertApi/include/debugAssertApi/debugAssertDisabler.h index 2163ecb..c6b32de 100644 --- a/libs/debugAssertApi/include/debugAssertApi/debugAssertDisabler.h +++ b/libs/debugAssertApi/include/debugAssertApi/debugAssertDisabler.h @@ -4,13 +4,12 @@ #pragma once #include -namespace Mso { -namespace DebugAsserts { +namespace Mso { namespace DebugAsserts { #ifdef DEBUG /** - Legacy APIs for disabling asserts + Legacy APIs for disabling asserts */ LIBLET_PUBLICAPI void DisableAssertTag(uint32_t tag) noexcept; LIBLET_PUBLICAPI void EnableAssertTag(uint32_t tag) noexcept; @@ -20,7 +19,10 @@ LIBLET_PUBLICAPI bool IsAssertTagDisabled(uint32_t tag) noexcept; inline void DisableAssertTag(uint32_t) noexcept {} inline void EnableAssertTag(uint32_t) noexcept {} -inline bool IsAssertTagDisabled(uint32_t) noexcept { return false; } +inline bool IsAssertTagDisabled(uint32_t) noexcept +{ + return false; +} #endif @@ -85,5 +87,4 @@ private: }; #endif -} // DebugAsserts -} // Mso +}} // namespace Mso::DebugAsserts diff --git a/libs/debugAssertApi/src/debugAssertApi.cpp b/libs/debugAssertApi/src/debugAssertApi.cpp index 6126ef7..63098ea 100644 --- a/libs/debugAssertApi/src/debugAssertApi.cpp +++ b/libs/debugAssertApi/src/debugAssertApi.cpp @@ -12,130 +12,129 @@ #ifdef DEBUG -namespace Mso { -namespace DebugAsserts { +namespace Mso { namespace DebugAsserts { struct Data { - std::set DisabledTags; - std::set Ignorers; - std::set Listeners; - AssertHandler Handler = nullptr; + std::set DisabledTags; + std::set Ignorers; + std::set Listeners; + AssertHandler Handler = nullptr; - static Data& Get() noexcept - { - // To avoid static initializer ordering issues, this object is created on demand and purposely leaked - static auto s_data = Construct(); - return *s_data; - } + static Data& Get() noexcept + { + // To avoid static initializer ordering issues, this object is created on demand and purposely leaked + static auto s_data = Construct(); + return *s_data; + } private: - static Data* Construct() noexcept - { - // xlsrv doesn't allow calling new from static initializers. Using std::allocator instead, which has been modified to call malloc. - std::allocator alloc; - auto p = alloc.allocate(1); - alloc.construct(p); - return p; - } + static Data* Construct() noexcept + { + // xlsrv doesn't allow calling new from static initializers. Using std::allocator instead, which has been modified + // to call malloc. + std::allocator alloc; + auto p = alloc.allocate(1); + alloc.construct(p); + return p; + } }; void DisableAssertTag(uint32_t tag) noexcept { - Data::Get().DisabledTags.insert(tag); + Data::Get().DisabledTags.insert(tag); } void EnableAssertTag(uint32_t tag) noexcept { - Data::Get().DisabledTags.erase(tag); + Data::Get().DisabledTags.erase(tag); } bool IsAssertTagDisabled(uint32_t tag) noexcept { - const auto& disabledTags = Data::Get().DisabledTags; - return (disabledTags.find(tag) != std::end(disabledTags)); + const auto& disabledTags = Data::Get().DisabledTags; + return (disabledTags.find(tag) != std::end(disabledTags)); } void AddAssertIgnorer(AssertIgnorer ignorer) noexcept { - Data::Get().Ignorers.insert(ignorer); + Data::Get().Ignorers.insert(ignorer); } void RemoveAssertIgnorer(AssertIgnorer ignorer) noexcept { - Data::Get().Ignorers.erase(ignorer); + Data::Get().Ignorers.erase(ignorer); } void AddAssertListener(AssertListener listener) noexcept { - Data::Get().Listeners.insert(listener); + Data::Get().Listeners.insert(listener); } void RemoveAssertListener(AssertListener listener) noexcept { - Data::Get().Listeners.erase(listener); + Data::Get().Listeners.erase(listener); } AssertHandler GetAssertHandler() noexcept { - return Data::Get().Handler; + return Data::Get().Handler; } AssertHandler SetAssertHandler(AssertHandler handler) noexcept { - std::swap(Data::Get().Handler, handler); - return handler; + std::swap(Data::Get().Handler, handler); + return handler; } static bool v_isInAssertHandler; -extern "C" int32_t MsoAssertSzTagProc(const MsoAssertParams& params, _Printf_format_string_ const char* szFormat, va_list argList) noexcept +extern "C" int32_t +MsoAssertSzTagProc(const MsoAssertParams& params, _Printf_format_string_ const char* szFormat, va_list argList) noexcept { - if (IsAssertTagDisabled(params.dwTag)) - return c_assertIgnore; + if (IsAssertTagDisabled(params.dwTag)) + return c_assertIgnore; - char assertMessage[4096]; - (void) vsnprintf(assertMessage, sizeof(assertMessage), szFormat, argList); - params.framesToSkip++; + char assertMessage[4096]; + (void)vsnprintf(assertMessage, sizeof(assertMessage), szFormat, argList); + params.framesToSkip++; - const auto& data = Data::Get(); - for (const auto& ignorer : data.Ignorers) - { - if (ignorer(params, assertMessage)) - return c_assertIgnore; - } - - for (const auto& listener : data.Listeners) - { - listener(params, assertMessage); - } + const auto& data = Data::Get(); + for (const auto& ignorer : data.Ignorers) + { + if (ignorer(params, assertMessage)) + return c_assertIgnore; + } - if (data.Handler) - { - Mso::TRestorer restoreInAssertHandler(v_isInAssertHandler, true); - return static_cast(data.Handler(params, assertMessage)); - } + for (const auto& listener : data.Listeners) + { + listener(params, assertMessage); + } - return c_assertIgnore; + if (data.Handler) + { + Mso::TRestorer restoreInAssertHandler(v_isInAssertHandler, true); + return static_cast(data.Handler(params, assertMessage)); + } + + return c_assertIgnore; } bool IsInAssertHandler() noexcept { - return v_isInAssertHandler; + return v_isInAssertHandler; } -} // DebugAsserts -} // Mso - +}} // namespace Mso::DebugAsserts LIBLET_PUBLICAPI_APPLE MSOAPI_(void) MsoFAddIgnoredAssertTag(uint32_t tag) noexcept { - Mso::DebugAsserts::DisableAssertTag(tag); + Mso::DebugAsserts::DisableAssertTag(tag); } LIBLET_PUBLICAPI_APPLE MSOAPI_(void) MsoFRemoveIgnoredAssertTag(uint32_t tag) noexcept { - Mso::DebugAsserts::EnableAssertTag(tag); + Mso::DebugAsserts::EnableAssertTag(tag); } #endif // DEBUG diff --git a/libs/eventWaitHandle/include/eventWaitHandle/eventWaitHandle.h b/libs/eventWaitHandle/include/eventWaitHandle/eventWaitHandle.h index 7e9e0ce..6ab282d 100644 --- a/libs/eventWaitHandle/include/eventWaitHandle/eventWaitHandle.h +++ b/libs/eventWaitHandle/include/eventWaitHandle/eventWaitHandle.h @@ -9,28 +9,27 @@ #include #include -namespace Mso { -namespace Async { +namespace Mso { namespace Async { //! Shared event wait handle interface used by ManualResetEvent and AutoResetEvent. //! Since, ManualResetEvent and AutoResetEvent are most commonly used between different threads, we used //! shared ownership based on ref counting to ensure proper lifetime of the synchronization events. struct IEventWaitHandle : Mso::IRefCounted { - virtual void Set() const noexcept = 0; - virtual void Reset() const noexcept = 0; - virtual void Wait() const noexcept = 0; - virtual bool WaitFor(const std::chrono::milliseconds& waitDuration) const noexcept = 0; + virtual void Set() const noexcept = 0; + virtual void Reset() const noexcept = 0; + virtual void Wait() const noexcept = 0; + virtual bool WaitFor(const std::chrono::milliseconds& waitDuration) const noexcept = 0; }; //! State of the IEventWaitHandle. enum class EventWaitHandleState : int32_t { - //! Threads are blocked when calling Wait() or WaitFor() methods. - NotSet, + //! Threads are blocked when calling Wait() or WaitFor() methods. + NotSet, - //! Threads are allowed to proceed or getting unblocked when calling Wait() or WaitFor() methods. - IsSet, + //! Threads are allowed to proceed or getting unblocked when calling Wait() or WaitFor() methods. + IsSet, }; //! Notifies one or more waiting threads that an event has occurred. This class cannot be inherited. @@ -56,59 +55,55 @@ enum class EventWaitHandleState : int32_t class ManualResetEvent final { public: - //! Creates new ManualResetEvent with the non-signaling state. - ManualResetEvent() noexcept : ManualResetEvent { EventWaitHandleState::NotSet } - { - } + //! Creates new ManualResetEvent with the non-signaling state. + ManualResetEvent() noexcept : ManualResetEvent{EventWaitHandleState::NotSet} {} - //! Creates new ManualResetEvent with the requested signaling state. - LIBLET_PUBLICAPI explicit ManualResetEvent(EventWaitHandleState state) noexcept; + //! Creates new ManualResetEvent with the requested signaling state. + LIBLET_PUBLICAPI explicit ManualResetEvent(EventWaitHandleState state) noexcept; - //! Creates new ManualResetEvent with the provided handle. - ManualResetEvent(IEventWaitHandle& handle) noexcept : m_handle { &handle } - { - } + //! Creates new ManualResetEvent with the provided handle. + ManualResetEvent(IEventWaitHandle& handle) noexcept : m_handle{&handle} {} - ManualResetEvent(const ManualResetEvent&) = default; - ManualResetEvent& operator=(const ManualResetEvent&) = default; + ManualResetEvent(const ManualResetEvent&) = default; + ManualResetEvent& operator=(const ManualResetEvent&) = default; - //! No move semantic - ManualResetEvent(ManualResetEvent&&) = delete; - ManualResetEvent& operator=(ManualResetEvent&&) = delete; + //! No move semantic + ManualResetEvent(ManualResetEvent&&) = delete; + ManualResetEvent& operator=(ManualResetEvent&&) = delete; - //! Sets the state of the event to signaled, which allows one or more waiting threads to proceed. - void Set() const noexcept - { - m_handle->Set(); - } + //! Sets the state of the event to signaled, which allows one or more waiting threads to proceed. + void Set() const noexcept + { + m_handle->Set(); + } - //! Sets the state of the event to non-signaled state, which causes waiting threads to block. - void Reset() const noexcept - { - m_handle->Reset(); - } + //! Sets the state of the event to non-signaled state, which causes waiting threads to block. + void Reset() const noexcept + { + m_handle->Reset(); + } - //! Blocks thread indefinitely and waits for the event signaling state. - void Wait() const noexcept - { - m_handle->Wait(); - } + //! Blocks thread indefinitely and waits for the event signaling state. + void Wait() const noexcept + { + m_handle->Wait(); + } - //! Blocks thread for waitDuration time and waits for the event signaling state. - template - bool WaitFor(const std::chrono::duration& waitDuration) const noexcept - { - return m_handle->WaitFor(std::chrono::duration_cast(waitDuration)); - } + //! Blocks thread for waitDuration time and waits for the event signaling state. + template + bool WaitFor(const std::chrono::duration& waitDuration) const noexcept + { + return m_handle->WaitFor(std::chrono::duration_cast(waitDuration)); + } - //! Gets the internal event handle. - IEventWaitHandle& GetHandle() const noexcept - { - return *m_handle; - } + //! Gets the internal event handle. + IEventWaitHandle& GetHandle() const noexcept + { + return *m_handle; + } private: - Mso::TCntPtr m_handle; + Mso::TCntPtr m_handle; }; //! Notifies a waiting thread that an event has occurred. This class cannot be inherited. @@ -130,62 +125,57 @@ private: class AutoResetEvent final { public: - //! Creates new AutoResetEvent with the non-signaling state. - AutoResetEvent() noexcept : AutoResetEvent { EventWaitHandleState::NotSet } - { - } + //! Creates new AutoResetEvent with the non-signaling state. + AutoResetEvent() noexcept : AutoResetEvent{EventWaitHandleState::NotSet} {} - //! Creates new AutoResetEvent with the requested signaling state. - LIBLET_PUBLICAPI explicit AutoResetEvent(EventWaitHandleState state) noexcept; + //! Creates new AutoResetEvent with the requested signaling state. + LIBLET_PUBLICAPI explicit AutoResetEvent(EventWaitHandleState state) noexcept; - //! Creates new AutoResetEvent with the provided handle. Crash if handle is null. - AutoResetEvent(IEventWaitHandle& handle) noexcept : m_handle { &handle } - { - } + //! Creates new AutoResetEvent with the provided handle. Crash if handle is null. + AutoResetEvent(IEventWaitHandle& handle) noexcept : m_handle{&handle} {} - AutoResetEvent(const AutoResetEvent&) = default; - AutoResetEvent& operator=(const AutoResetEvent&) = default; + AutoResetEvent(const AutoResetEvent&) = default; + AutoResetEvent& operator=(const AutoResetEvent&) = default; - // No move semantic - AutoResetEvent(AutoResetEvent&&) = delete; - AutoResetEvent& operator=(AutoResetEvent&&) = delete; + // No move semantic + AutoResetEvent(AutoResetEvent&&) = delete; + AutoResetEvent& operator=(AutoResetEvent&&) = delete; - //! Sets the state of the event to signaled, which allows at most one waiting thread to proceed. - void Set() const noexcept - { - m_handle->Set(); - } + //! Sets the state of the event to signaled, which allows at most one waiting thread to proceed. + void Set() const noexcept + { + m_handle->Set(); + } - //! Sets the state of the event to non-signaled state, which causes waiting threads to block. - void Reset() const noexcept - { - m_handle->Reset(); - } + //! Sets the state of the event to non-signaled state, which causes waiting threads to block. + void Reset() const noexcept + { + m_handle->Reset(); + } - //! Blocks thread indefinitely and waits for the event signaling state. - void Wait() const noexcept - { - m_handle->Wait(); - } + //! Blocks thread indefinitely and waits for the event signaling state. + void Wait() const noexcept + { + m_handle->Wait(); + } - //! Blocks thread for waitDuration time and waits for the event signaling state. - template - bool WaitFor(const std::chrono::duration& waitDuration) const noexcept - { - return m_handle->WaitFor(std::chrono::duration_cast(waitDuration)); - } + //! Blocks thread for waitDuration time and waits for the event signaling state. + template + bool WaitFor(const std::chrono::duration& waitDuration) const noexcept + { + return m_handle->WaitFor(std::chrono::duration_cast(waitDuration)); + } - //! Gets the internal event handle. - IEventWaitHandle& GetHandle() const noexcept - { - return *m_handle; - } + //! Gets the internal event handle. + IEventWaitHandle& GetHandle() const noexcept + { + return *m_handle; + } private: - Mso::TCntPtr m_handle; + Mso::TCntPtr m_handle; }; -} // namespace Async -} // namespace Mso +}} // namespace Mso::Async #endif // LIBLET_DISPATCHQUEUE_EVENTWAITHANDLE_H diff --git a/libs/eventWaitHandle/src/eventWaitHandle.h b/libs/eventWaitHandle/src/eventWaitHandle.h index ed883e1..f6d2b1e 100644 --- a/libs/eventWaitHandle/src/eventWaitHandle.h +++ b/libs/eventWaitHandle/src/eventWaitHandle.h @@ -7,17 +7,16 @@ #include #include -namespace Mso { -namespace Async { +namespace Mso { namespace Async { using TimePoint = std::chrono::time_point; struct WaitTimePoint { - bool IsInfinite { false }; - bool ShouldUpdateWaitDuration { false }; - std::chrono::milliseconds WaitDuration {}; - TimePoint WaitUntil {}; + bool IsInfinite{false}; + bool ShouldUpdateWaitDuration{false}; + std::chrono::milliseconds WaitDuration{}; + TimePoint WaitUntil{}; }; // Implementation of the IEventWaitHandle interface @@ -25,84 +24,82 @@ template class EventWaitHandle final : public Mso::RefCountedObject { public: - EventWaitHandle(bool isAutoReset, EventWaitHandleState state) noexcept - : m_isAutoReset { isAutoReset } - , m_state { state } - { - } + EventWaitHandle(bool isAutoReset, EventWaitHandleState state) noexcept : m_isAutoReset{isAutoReset}, m_state{state} {} public: // IEventWaitHandle - void Set() const noexcept override - { - std::lock_guard lock { m_mutex }; - m_state = EventWaitHandleState::IsSet; + void Set() const noexcept override + { + std::lock_guard lock{m_mutex}; + m_state = EventWaitHandleState::IsSet; - // Notify under the lock to avoid missed signals in case if Wait loop is between - // checking variable and calling wait for signal API. - if (m_isAutoReset) - { - m_cond.NotifyOne(); - } - else - { - m_cond.NotifyAll(); - } - } + // Notify under the lock to avoid missed signals in case if Wait loop is between + // checking variable and calling wait for signal API. + if (m_isAutoReset) + { + m_cond.NotifyOne(); + } + else + { + m_cond.NotifyAll(); + } + } - void Reset() const noexcept override - { - std::lock_guard lock { m_mutex }; - m_state = EventWaitHandleState::NotSet; - } + void Reset() const noexcept override + { + std::lock_guard lock{m_mutex}; + m_state = EventWaitHandleState::NotSet; + } - void Wait() const noexcept override - { - WaitTimePoint waitTimePoint {}; - waitTimePoint.IsInfinite = true; - VerifyElseCrashSzTag(WaitUntil(waitTimePoint), "Must not timeout", 0x026e348b /* tag_c19sl */); - } + void Wait() const noexcept override + { + WaitTimePoint waitTimePoint{}; + waitTimePoint.IsInfinite = true; + VerifyElseCrashSzTag(WaitUntil(waitTimePoint), "Must not timeout", 0x026e348b /* tag_c19sl */); + } - bool WaitFor(const std::chrono::milliseconds& waitDuration) const noexcept override - { - VerifyElseCrashSzTag(waitDuration.count() < std::numeric_limits::max(), - "waitDuration must not exceed uint32_t size for milliseconds.", 0x026e348c /* tag_c19sm */); + bool WaitFor(const std::chrono::milliseconds& waitDuration) const noexcept override + { + VerifyElseCrashSzTag( + waitDuration.count() < std::numeric_limits::max(), + "waitDuration must not exceed uint32_t size for milliseconds.", + 0x026e348c /* tag_c19sm */); - auto now = std::chrono::system_clock::now(); + auto now = std::chrono::system_clock::now(); - WaitTimePoint waitTimePoint {}; - waitTimePoint.WaitDuration = waitDuration; - waitTimePoint.WaitUntil = now + waitDuration; - VerifyElseCrashSzTag(waitTimePoint.WaitUntil >= now, "waitDuration causes clock overflow", 0x026e348d /* tag_c19sn */); + WaitTimePoint waitTimePoint{}; + waitTimePoint.WaitDuration = waitDuration; + waitTimePoint.WaitUntil = now + waitDuration; + VerifyElseCrashSzTag( + waitTimePoint.WaitUntil >= now, "waitDuration causes clock overflow", 0x026e348d /* tag_c19sn */); - return WaitUntil(waitTimePoint); - } + return WaitUntil(waitTimePoint); + } private: - bool WaitUntil(WaitTimePoint& timePoint) const noexcept - { - std::lock_guard lock { m_mutex }; - while (m_state != EventWaitHandleState::IsSet) - { - if (!m_cond.WaitUntil(m_mutex, timePoint)) - { - return false; - } - } + bool WaitUntil(WaitTimePoint& timePoint) const noexcept + { + std::lock_guard lock{m_mutex}; + while (m_state != EventWaitHandleState::IsSet) + { + if (!m_cond.WaitUntil(m_mutex, timePoint)) + { + return false; + } + } - if (m_isAutoReset) - { - m_state = EventWaitHandleState::NotSet; - } + if (m_isAutoReset) + { + m_state = EventWaitHandleState::NotSet; + } - return true; - } + return true; + } private: - mutable TMutex m_mutex; - mutable TConditionVariable m_cond; - const bool m_isAutoReset; - mutable EventWaitHandleState m_state; + mutable TMutex m_mutex; + mutable TConditionVariable m_cond; + const bool m_isAutoReset; + mutable EventWaitHandleState m_state; }; -} // namespace Async -} // namespace Mso +}} // namespace Mso::Async diff --git a/libs/eventWaitHandle/src/eventWaitHandle_posix.cpp b/libs/eventWaitHandle/src/eventWaitHandle_posix.cpp index aa128a1..930eb78 100644 --- a/libs/eventWaitHandle/src/eventWaitHandle_posix.cpp +++ b/libs/eventWaitHandle/src/eventWaitHandle_posix.cpp @@ -5,93 +5,92 @@ #include "eventWaitHandle.h" #include -namespace Mso { -namespace Async { +namespace Mso { namespace Async { namespace { // Mutex class based on pthread_mutex_t that meets BasicLockable standard requirements. struct PThreadMutex { - ~PThreadMutex() noexcept - { - pthread_mutex_destroy(&Handle); - } + ~PThreadMutex() noexcept + { + pthread_mutex_destroy(&Handle); + } - void lock() noexcept - { - pthread_mutex_lock(&Handle); - } + void lock() noexcept + { + pthread_mutex_lock(&Handle); + } - void unlock() noexcept - { - pthread_mutex_unlock(&Handle); - } + void unlock() noexcept + { + pthread_mutex_unlock(&Handle); + } - pthread_mutex_t Handle = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_t Handle = PTHREAD_MUTEX_INITIALIZER; }; // pthread_cond_t wrapper struct ConditionVariable { - ~ConditionVariable() noexcept - { - pthread_cond_destroy(&m_cond); - } + ~ConditionVariable() noexcept + { + pthread_cond_destroy(&m_cond); + } - void NotifyOne() noexcept - { - pthread_cond_signal(&m_cond); - } + void NotifyOne() noexcept + { + pthread_cond_signal(&m_cond); + } - void NotifyAll() noexcept - { - pthread_cond_broadcast(&m_cond); - } + void NotifyAll() noexcept + { + pthread_cond_broadcast(&m_cond); + } - bool WaitUntil(PThreadMutex& mutex, const WaitTimePoint& waitTimePoint) noexcept - { - if (waitTimePoint.IsInfinite) - { - VerifyElseCrashSzTag(!pthread_cond_wait(&m_cond, &mutex.Handle), "pthread_cond_wait failed", 0x026e348e /* tag_c19so */); - return true; - } + bool WaitUntil(PThreadMutex& mutex, const WaitTimePoint& waitTimePoint) noexcept + { + if (waitTimePoint.IsInfinite) + { + VerifyElseCrashSzTag( + !pthread_cond_wait(&m_cond, &mutex.Handle), "pthread_cond_wait failed", 0x026e348e /* tag_c19so */); + return true; + } - auto tsWaitUntil = DurationToTimeSpec(waitTimePoint.WaitUntil.time_since_epoch()); - if (int error = pthread_cond_timedwait(&m_cond, &mutex.Handle, &tsWaitUntil)) - { - VerifyElseCrashSzTag(error == ETIMEDOUT, "pthread_cond_wait failed", 0x026e348f /* tag_c19sp */); - return false; - } + auto tsWaitUntil = DurationToTimeSpec(waitTimePoint.WaitUntil.time_since_epoch()); + if (int error = pthread_cond_timedwait(&m_cond, &mutex.Handle, &tsWaitUntil)) + { + VerifyElseCrashSzTag(error == ETIMEDOUT, "pthread_cond_wait failed", 0x026e348f /* tag_c19sp */); + return false; + } - return true; - } + return true; + } private: - static timespec DurationToTimeSpec(const TimePoint::duration& duration) noexcept - { - using namespace std::chrono; - timespec ts; - ts.tv_sec = static_cast(duration_cast(duration).count()); - ts.tv_nsec = static_cast(duration_cast(duration % seconds { 1 }).count()); - return ts; - } + static timespec DurationToTimeSpec(const TimePoint::duration& duration) noexcept + { + using namespace std::chrono; + timespec ts; + ts.tv_sec = static_cast(duration_cast(duration).count()); + ts.tv_nsec = static_cast(duration_cast(duration % seconds{1}).count()); + return ts; + } private: - pthread_cond_t m_cond = PTHREAD_COND_INITIALIZER; + pthread_cond_t m_cond = PTHREAD_COND_INITIALIZER; }; } // namespace LIBLET_PUBLICAPI ManualResetEvent::ManualResetEvent(EventWaitHandleState state) noexcept - : m_handle { Mso::Make>(/*isAutoReset:*/false, state) } + : m_handle{Mso::Make>(/*isAutoReset:*/ false, state)} { } LIBLET_PUBLICAPI AutoResetEvent::AutoResetEvent(EventWaitHandleState state) noexcept - : m_handle { Mso::Make>(/*isAutoReset:*/true, state) } + : m_handle{Mso::Make>(/*isAutoReset:*/ true, state)} { } -} // namespace Async -} // namespace Mso +}} // namespace Mso::Async diff --git a/libs/eventWaitHandle/src/eventWaitHandle_win.cpp b/libs/eventWaitHandle/src/eventWaitHandle_win.cpp index bc03e79..b8074d1 100644 --- a/libs/eventWaitHandle/src/eventWaitHandle_win.cpp +++ b/libs/eventWaitHandle/src/eventWaitHandle_win.cpp @@ -10,95 +10,90 @@ //! These APIs were added in Windows Vista and considered to be more //! lightweight when events created with CreateEventEx Windows API. -namespace Mso { -namespace Async { +namespace Mso { namespace Async { namespace { // Mutex class based on SRWLOCK that meets BasicLockable standard requirements. struct SRWMutex { - _Requires_lock_not_held_(this->Handle) - _Acquires_lock_(this->Handle) - void lock() noexcept - { - AcquireSRWLockExclusive(&Handle); - } + _Requires_lock_not_held_(this->Handle) _Acquires_lock_(this->Handle) void lock() noexcept + { + AcquireSRWLockExclusive(&Handle); + } - _Requires_lock_held_(this->Handle) - _Releases_lock_(this->Handle) - void unlock() noexcept - { - ReleaseSRWLockExclusive(&Handle); - } + _Requires_lock_held_(this->Handle) _Releases_lock_(this->Handle) void unlock() noexcept + { + ReleaseSRWLockExclusive(&Handle); + } - SRWLOCK Handle{ SRWLOCK_INIT }; + SRWLOCK Handle{SRWLOCK_INIT}; }; // Windows CONDITION_VARIABLE wrapper struct ConditionVariable { - void NotifyOne() noexcept - { - WakeConditionVariable(&m_cond); - } + void NotifyOne() noexcept + { + WakeConditionVariable(&m_cond); + } - void NotifyAll() noexcept - { - WakeAllConditionVariable(&m_cond); - } + void NotifyAll() noexcept + { + WakeAllConditionVariable(&m_cond); + } - bool WaitUntil(SRWMutex& mutex, WaitTimePoint& waitTimePoint) noexcept - { - if (!SleepConditionVariableSRW(&m_cond, &mutex.Handle, GetWaitTimeInMs(waitTimePoint), 0)) - { - VerifyElseCrashSzTag(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW failed.", 0x026e3490 /* tag_c19sq */); - return false; - } + bool WaitUntil(SRWMutex& mutex, WaitTimePoint& waitTimePoint) noexcept + { + if (!SleepConditionVariableSRW(&m_cond, &mutex.Handle, GetWaitTimeInMs(waitTimePoint), 0)) + { + VerifyElseCrashSzTag( + GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW failed.", 0x026e3490 /* tag_c19sq */); + return false; + } - return true; - } + return true; + } private: - static uint32_t GetWaitTimeInMs(WaitTimePoint& waitTimePoint) noexcept - { - if (waitTimePoint.IsInfinite) - { - return INFINITE; - } + static uint32_t GetWaitTimeInMs(WaitTimePoint& waitTimePoint) noexcept + { + if (waitTimePoint.IsInfinite) + { + return INFINITE; + } - // For the very first time here we use duration provided by user. - // If we get here again, then it means that the condition_variable was woken up - // due to sporatic wakeups, and we have to recalculate the wait duration. - if (waitTimePoint.ShouldUpdateWaitDuration) - { - using namespace std::chrono; - auto timeLeft = duration_cast(waitTimePoint.WaitUntil - system_clock::now()); - // Make sure that we do not have negative duration because we waited beyond the target time point, - // or because system_clock::now() gave inacccurate time due to internal implementation. - waitTimePoint.WaitDuration = std::max(timeLeft, milliseconds { 0 }); - } + // For the very first time here we use duration provided by user. + // If we get here again, then it means that the condition_variable was woken up + // due to sporatic wakeups, and we have to recalculate the wait duration. + if (waitTimePoint.ShouldUpdateWaitDuration) + { + using namespace std::chrono; + auto timeLeft = duration_cast(waitTimePoint.WaitUntil - system_clock::now()); + // Make sure that we do not have negative duration because we waited beyond the target time point, + // or because system_clock::now() gave inacccurate time due to internal implementation. + waitTimePoint.WaitDuration = std::max(timeLeft, milliseconds{0}); + } - waitTimePoint.ShouldUpdateWaitDuration = true; + waitTimePoint.ShouldUpdateWaitDuration = true; - return static_cast(waitTimePoint.WaitDuration.count()); - } + return static_cast(waitTimePoint.WaitDuration.count()); + } private: - CONDITION_VARIABLE m_cond { CONDITION_VARIABLE_INIT }; + CONDITION_VARIABLE m_cond{CONDITION_VARIABLE_INIT}; }; } // namespace LIBLET_PUBLICAPI ManualResetEvent::ManualResetEvent(EventWaitHandleState state) noexcept - : m_handle { Mso::Make>(/*isAutoReset:*/false, state) } + : m_handle{Mso::Make>(/*isAutoReset:*/ false, state)} { } LIBLET_PUBLICAPI AutoResetEvent::AutoResetEvent(EventWaitHandleState state) noexcept - : m_handle { Mso::Make>(/*isAutoReset:*/true, state) } + : m_handle{Mso::Make>(/*isAutoReset:*/ true, state)} { } -} // namespace Async -} // namespace Mso +}} // namespace Mso::Async diff --git a/libs/eventWaitHandle/tests/eventWaitHandleTest.cpp b/libs/eventWaitHandle/tests/eventWaitHandleTest.cpp index d017234..b7ea160 100644 --- a/libs/eventWaitHandle/tests/eventWaitHandleTest.cpp +++ b/libs/eventWaitHandle/tests/eventWaitHandleTest.cpp @@ -11,327 +11,323 @@ using namespace std::chrono_literals; -namespace Mso { -namespace Async { -namespace Test { +namespace Mso { namespace Async { namespace Test { -TEST_CLASS(EventWaitHandleTest) +TEST_CLASS (EventWaitHandleTest) { - //TODO: enable MemoryLeakDetection - //MemoryLeakDetectionHook::TrackPerTest m_trackLeakPerTest; + // TODO: enable MemoryLeakDetection + // MemoryLeakDetectionHook::TrackPerTest m_trackLeakPerTest; - TEST_METHOD(ManualResetEvent_ctor_default) - { - ManualResetEvent ev; - TestCheck(&ev.GetHandle()); - } + TEST_METHOD(ManualResetEvent_ctor_default) + { + ManualResetEvent ev; + TestCheck(&ev.GetHandle()); + } - TEST_METHOD(ManualResetEvent_ctor_Signaling) - { - ManualResetEvent ev{ EventWaitHandleState::IsSet }; - TestCheck(&ev.GetHandle()); - ev.Wait(); - } + TEST_METHOD(ManualResetEvent_ctor_Signaling) + { + ManualResetEvent ev{EventWaitHandleState::IsSet}; + TestCheck(&ev.GetHandle()); + ev.Wait(); + } - TEST_METHOD(ManualResetEvent_ctor_NotSignaling) - { - ManualResetEvent ev { EventWaitHandleState::NotSet }; - TestCheck(&ev.GetHandle()); - TestCheck(!ev.WaitFor(1ms)); // Must timeout - } + TEST_METHOD(ManualResetEvent_ctor_NotSignaling) + { + ManualResetEvent ev{EventWaitHandleState::NotSet}; + TestCheck(&ev.GetHandle()); + TestCheck(!ev.WaitFor(1ms)); // Must timeout + } - TEST_METHOD(ManualResetEvent_ctor_handle) - { - ManualResetEvent ev1; - ManualResetEvent ev2 { ev1.GetHandle() }; - TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); - } + TEST_METHOD(ManualResetEvent_ctor_handle) + { + ManualResetEvent ev1; + ManualResetEvent ev2{ev1.GetHandle()}; + TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); + } - TEST_METHOD(ManualResetEvent_ctor_copy) - { - ManualResetEvent ev1; - ManualResetEvent ev2{ ev1 }; // Copy - TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); - } + TEST_METHOD(ManualResetEvent_ctor_copy) + { + ManualResetEvent ev1; + ManualResetEvent ev2{ev1}; // Copy + TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); + } - TEST_METHOD(ManualResetEvent_assignment_copy) - { - ManualResetEvent ev1; - ManualResetEvent ev2; - ev2 = ev1; // Copy - TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); - } + TEST_METHOD(ManualResetEvent_assignment_copy) + { + ManualResetEvent ev1; + ManualResetEvent ev2; + ev2 = ev1; // Copy + TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); + } - TEST_METHOD(ManualResetEvent_Set) - { - std::atomic value{ 0 }; - ManualResetEvent ev; - // Note that we capture by value to make a copy of the pointer. - std::thread th([ev, &value]() noexcept { - ev.Set(); - ++value; - }); - ev.Wait(); - th.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(ManualResetEvent_Set) + { + std::atomic value{0}; + ManualResetEvent ev; + // Note that we capture by value to make a copy of the pointer. + std::thread th([ev, &value]() noexcept { + ev.Set(); + ++value; + }); + ev.Wait(); + th.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(ManualResetEvent_NoAutoReset) - { - std::atomic value{ 0 }; - ManualResetEvent ev; - std::thread th([ev, &value]() noexcept { - ev.Set(); - ++value; - }); - ev.Wait(); - ev.Wait(); // Second Wait succeeds because it is not auto-reset. - th.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(ManualResetEvent_NoAutoReset) + { + std::atomic value{0}; + ManualResetEvent ev; + std::thread th([ev, &value]() noexcept { + ev.Set(); + ++value; + }); + ev.Wait(); + ev.Wait(); // Second Wait succeeds because it is not auto-reset. + th.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(ManualResetEvent_TwoWaitThreadsWakeup) - { - ManualResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - ev.Wait(); - ++value; - }); - std::thread th2([ev, &value]() noexcept { - ev.Wait(); - ++value; - }); - ev.Set(); - th1.join(); - th2.join(); - TestCheckEqual(2, value.load()); - } + TEST_METHOD(ManualResetEvent_TwoWaitThreadsWakeup) + { + ManualResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + ev.Wait(); + ++value; + }); + std::thread th2([ev, &value]() noexcept { + ev.Wait(); + ++value; + }); + ev.Set(); + th1.join(); + th2.join(); + TestCheckEqual(2, value.load()); + } - TEST_METHOD(ManualResetEvent_Reset) - { - ManualResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - ev.Wait(); - ++value; - ev.Reset(); - }); - ev.Set(); - th1.join(); - TestCheckEqual(1, value.load()); - std::thread th2([ev, &value]() noexcept { - ev.Wait(); - ++value; - }); - TestCheckEqual(1, value.load()); // Make sure that th2 waits - ev.Set(); - th2.join(); - TestCheckEqual(2, value.load()); - } + TEST_METHOD(ManualResetEvent_Reset) + { + ManualResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + ev.Wait(); + ++value; + ev.Reset(); + }); + ev.Set(); + th1.join(); + TestCheckEqual(1, value.load()); + std::thread th2([ev, &value]() noexcept { + ev.Wait(); + ++value; + }); + TestCheckEqual(1, value.load()); // Make sure that th2 waits + ev.Set(); + th2.join(); + TestCheckEqual(2, value.load()); + } - TEST_METHOD(ManualResetEvent_WaitFor0) - { - ManualResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - TestCheck(!ev.WaitFor(0ms)); // Must always timeout in our case. - ++value; - }); - th1.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(ManualResetEvent_WaitFor0) + { + ManualResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + TestCheck(!ev.WaitFor(0ms)); // Must always timeout in our case. + ++value; + }); + th1.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(ManualResetEvent_WaitFor1) - { - ManualResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - TestCheck(!ev.WaitFor(1ms)); // Must always timeout in our case. - ++value; - }); - th1.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(ManualResetEvent_WaitFor1) + { + ManualResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + TestCheck(!ev.WaitFor(1ms)); // Must always timeout in our case. + ++value; + }); + th1.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(ManualResetEvent_WaitFor_Succeed) - { - ManualResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - TestCheck(ev.WaitFor(1000s)); // Must succeed because we call Set. - ++value; - }); - ev.Set(); - th1.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(ManualResetEvent_WaitFor_Succeed) + { + ManualResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + TestCheck(ev.WaitFor(1000s)); // Must succeed because we call Set. + ++value; + }); + ev.Set(); + th1.join(); + TestCheckEqual(1, value.load()); + } - TESTMETHOD_REQUIRES_SEH(ManualResetEvent_WaitFor_CrashForOverflow) - { - //TODO: enable MemoryLeakDetection - //TEST_DISABLE_MEMORY_LEAK_DETECTION(); - ManualResetEvent ev; - TestCheckCrash(ev.WaitFor(std::chrono::seconds::max())); - } + TESTMETHOD_REQUIRES_SEH(ManualResetEvent_WaitFor_CrashForOverflow) + { + // TODO: enable MemoryLeakDetection + // TEST_DISABLE_MEMORY_LEAK_DETECTION(); + ManualResetEvent ev; + TestCheckCrash(ev.WaitFor(std::chrono::seconds::max())); + } - TEST_METHOD(ManualResetEvent_WaitFor_CrashForInfinite) - { - //TODO: enable MemoryLeakDetection - //TEST_DISABLE_MEMORY_LEAK_DETECTION(); - ManualResetEvent ev; - TestCheckCrash(ev.WaitFor(std::chrono::milliseconds(std::numeric_limits::max()))); - } + TEST_METHOD(ManualResetEvent_WaitFor_CrashForInfinite) + { + // TODO: enable MemoryLeakDetection + // TEST_DISABLE_MEMORY_LEAK_DETECTION(); + ManualResetEvent ev; + TestCheckCrash(ev.WaitFor(std::chrono::milliseconds(std::numeric_limits::max()))); + } - TEST_METHOD(AutoResetEvent_ctor_default) - { - AutoResetEvent ev; - TestCheck(&ev.GetHandle()); - } + TEST_METHOD(AutoResetEvent_ctor_default) + { + AutoResetEvent ev; + TestCheck(&ev.GetHandle()); + } - TEST_METHOD(AutoResetEvent_ctor_Signaling) - { - AutoResetEvent ev { EventWaitHandleState::IsSet }; - TestCheck(&ev.GetHandle()); - ev.Wait(); - } + TEST_METHOD(AutoResetEvent_ctor_Signaling) + { + AutoResetEvent ev{EventWaitHandleState::IsSet}; + TestCheck(&ev.GetHandle()); + ev.Wait(); + } - TEST_METHOD(AutoResetEvent_ctor_NotSignaling) - { - AutoResetEvent ev { EventWaitHandleState::NotSet }; - TestCheck(&ev.GetHandle()); - TestCheck(!ev.WaitFor(1ms)); // Must timeout - } + TEST_METHOD(AutoResetEvent_ctor_NotSignaling) + { + AutoResetEvent ev{EventWaitHandleState::NotSet}; + TestCheck(&ev.GetHandle()); + TestCheck(!ev.WaitFor(1ms)); // Must timeout + } - TEST_METHOD(AutoResetEvent_ctor_handle) - { - AutoResetEvent ev1; - AutoResetEvent ev2 { ev1.GetHandle() }; - TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); - } + TEST_METHOD(AutoResetEvent_ctor_handle) + { + AutoResetEvent ev1; + AutoResetEvent ev2{ev1.GetHandle()}; + TestCheck(&ev1.GetHandle() == &ev2.GetHandle()); + } - TEST_METHOD(AutoResetEvent_Set) - { - std::atomic value{ 0 }; - AutoResetEvent ev; - // Note that we capture by value to make a copy of the pointer. - std::thread th([ev, &value]() noexcept { - ev.Set(); - ++value; - }); - ev.Wait(); - th.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(AutoResetEvent_Set) + { + std::atomic value{0}; + AutoResetEvent ev; + // Note that we capture by value to make a copy of the pointer. + std::thread th([ev, &value]() noexcept { + ev.Set(); + ++value; + }); + ev.Wait(); + th.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(AutoResetEvent_AutoReset) - { - std::atomic value{ 0 }; - AutoResetEvent ev; - std::thread th([ev, &value]() noexcept { - ev.Set(); - ++value; - }); - ev.Wait(); - TestCheck(!ev.WaitFor(1ms)); // Second Wait fails because it is auto-reset. - th.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(AutoResetEvent_AutoReset) + { + std::atomic value{0}; + AutoResetEvent ev; + std::thread th([ev, &value]() noexcept { + ev.Set(); + ++value; + }); + ev.Wait(); + TestCheck(!ev.WaitFor(1ms)); // Second Wait fails because it is auto-reset. + th.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(AutoResetEvent_TwoWaitThreadsWakeup) - { - AutoResetEvent ev; - ManualResetEvent valueChanged; - std::atomic value{ 0 }; - std::thread th1([ev, &value, valueChanged]() noexcept { - ev.Wait(); - ++value; - valueChanged.Set(); - }); - std::thread th2([ev, &value, valueChanged]() noexcept { - ev.Wait(); - ++value; - valueChanged.Set(); - }); - ev.Set(); - valueChanged.Wait(); - TestCheckEqual(1, value.load()); - ev.Set(); - th1.join(); - th2.join(); - TestCheckEqual(2, value.load()); - } + TEST_METHOD(AutoResetEvent_TwoWaitThreadsWakeup) + { + AutoResetEvent ev; + ManualResetEvent valueChanged; + std::atomic value{0}; + std::thread th1([ev, &value, valueChanged]() noexcept { + ev.Wait(); + ++value; + valueChanged.Set(); + }); + std::thread th2([ev, &value, valueChanged]() noexcept { + ev.Wait(); + ++value; + valueChanged.Set(); + }); + ev.Set(); + valueChanged.Wait(); + TestCheckEqual(1, value.load()); + ev.Set(); + th1.join(); + th2.join(); + TestCheckEqual(2, value.load()); + } - TEST_METHOD(AutoResetEvent_Reset) - { - AutoResetEvent ev; - std::atomic value{ 0 }; - ev.Set(); - ev.Reset(); - TestCheck(!ev.WaitFor(1ms)); // Make sure that ev is not signaling. - std::thread th([ev, &value]() noexcept { - ev.Wait(); - ++value; - }); - ev.Set(); - th.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(AutoResetEvent_Reset) + { + AutoResetEvent ev; + std::atomic value{0}; + ev.Set(); + ev.Reset(); + TestCheck(!ev.WaitFor(1ms)); // Make sure that ev is not signaling. + std::thread th([ev, &value]() noexcept { + ev.Wait(); + ++value; + }); + ev.Set(); + th.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(AutoResetEvent_WaitFor0) - { - AutoResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - TestCheck(!ev.WaitFor(0ms)); // Must always timeout in our case. - ++value; - }); - th1.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(AutoResetEvent_WaitFor0) + { + AutoResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + TestCheck(!ev.WaitFor(0ms)); // Must always timeout in our case. + ++value; + }); + th1.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(AutoResetEvent_WaitFor1) - { - AutoResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - TestCheck(!ev.WaitFor(1ms)); // Must always timeout in our case. - ++value; - }); - th1.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(AutoResetEvent_WaitFor1) + { + AutoResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + TestCheck(!ev.WaitFor(1ms)); // Must always timeout in our case. + ++value; + }); + th1.join(); + TestCheckEqual(1, value.load()); + } - TEST_METHOD(AutoResetEvent_WaitFor_Succeed) - { - AutoResetEvent ev; - std::atomic value{ 0 }; - std::thread th1([ev, &value]() noexcept { - TestCheck(ev.WaitFor(1000s)); // Must succeed because we call Set. - ++value; - }); - ev.Set(); - th1.join(); - TestCheckEqual(1, value.load()); - } + TEST_METHOD(AutoResetEvent_WaitFor_Succeed) + { + AutoResetEvent ev; + std::atomic value{0}; + std::thread th1([ev, &value]() noexcept { + TestCheck(ev.WaitFor(1000s)); // Must succeed because we call Set. + ++value; + }); + ev.Set(); + th1.join(); + TestCheckEqual(1, value.load()); + } - TESTMETHOD_REQUIRES_SEH(AutoResetEvent_WaitFor_CrashForOverflow) - { - //TODO: enable MemoryLeakDetection - //TEST_DISABLE_MEMORY_LEAK_DETECTION(); - AutoResetEvent ev; - TestCheckCrash(ev.WaitFor(std::chrono::seconds::max())); - } + TESTMETHOD_REQUIRES_SEH(AutoResetEvent_WaitFor_CrashForOverflow) + { + // TODO: enable MemoryLeakDetection + // TEST_DISABLE_MEMORY_LEAK_DETECTION(); + AutoResetEvent ev; + TestCheckCrash(ev.WaitFor(std::chrono::seconds::max())); + } - TESTMETHOD_REQUIRES_SEH(AutoResetEvent_WaitFor_CrashForInfinite) - { - //TODO: enable MemoryLeakDetection - //TEST_DISABLE_MEMORY_LEAK_DETECTION(); - AutoResetEvent ev; - TestCheckCrash(ev.WaitFor(std::chrono::milliseconds(std::numeric_limits::max()))); - } + TESTMETHOD_REQUIRES_SEH(AutoResetEvent_WaitFor_CrashForInfinite) + { + // TODO: enable MemoryLeakDetection + // TEST_DISABLE_MEMORY_LEAK_DETECTION(); + AutoResetEvent ev; + TestCheckCrash(ev.WaitFor(std::chrono::milliseconds(std::numeric_limits::max()))); + } }; -} // namespace Testing -} // namespace Async -} // namespace Mso +}}} // namespace Mso::Async::Test diff --git a/libs/functional/include/functional/functor.h b/libs/functional/include/functional/functor.h index 5f7b364..3db7ea0 100644 --- a/libs/functional/include/functional/functor.h +++ b/libs/functional/include/functional/functor.h @@ -2,25 +2,25 @@ // Licensed under the MIT license. /** - Mso::Functor is a replacement for std::function that uses intrusive reference - counting and is always non-throwing (even if it is wrapping a throwing function - object). Mso::Functor has the following semantics: + Mso::Functor is a replacement for std::function that uses intrusive reference + counting and is always non-throwing (even if it is wrapping a throwing function + object). Mso::Functor has the following semantics: - - Always performs a heap allocation when creating a new instance from a - function object, unless the function object is stateless. - - Are small (size of a TCntPtr). - - Cheap to copy and move. - - There will only be one outstanding copy of the function object given to - the Mso::Functor. - - Supports move-only function objects (e.g. a lambda capturing a unique_ptr), - unlike std::function<>. + - Always performs a heap allocation when creating a new instance from a + function object, unless the function object is stateless. + - Are small (size of a TCntPtr). + - Cheap to copy and move. + - There will only be one outstanding copy of the function object given to + the Mso::Functor. + - Supports move-only function objects (e.g. a lambda capturing a unique_ptr), + unlike std::function<>. - For throwing function objects you can use Mso::FunctorThrow. + For throwing function objects you can use Mso::FunctorThrow. - If you want to avoid the heap allocation overhead then you have two other choices: - - If the functor is not long lived and won't outlive the function object, - use Mso::FunctorRef. - - If you need to keep the functor for longer, use Mso::SmallFunctor. + If you want to avoid the heap allocation overhead then you have two other choices: + - If the functor is not long lived and won't outlive the function object, + use Mso::FunctorRef. + - If you need to keep the functor for longer, use Mso::SmallFunctor. */ #pragma once @@ -37,82 +37,75 @@ //! These are set of macros to generate code that depends on //! calling conventions and other function decorators. #ifdef __clang__ -#define MSO_EMIT_CDECL(func, cvOpt, refOpt, noexceptOpt) \ - func(, cvOpt, refOpt, noexceptOpt) +#define MSO_EMIT_CDECL(func, cvOpt, refOpt, noexceptOpt) func(, cvOpt, refOpt, noexceptOpt) #else -#define MSO_EMIT_CDECL(func, cvOpt, refOpt, noexceptOpt) \ - func(__cdecl, cvOpt, refOpt, noexceptOpt) +#define MSO_EMIT_CDECL(func, cvOpt, refOpt, noexceptOpt) func(__cdecl, cvOpt, refOpt, noexceptOpt) #endif #if !defined(__clang__) && defined(_M_CEE) -#define MSO_EMIT_CLRCALL(func, cvOpt, refOpt, noexceptOpt) \ - func(__clrcall, cvOpt, refOpt, noexceptOpt) +#define MSO_EMIT_CLRCALL(func, cvOpt, refOpt, noexceptOpt) func(__clrcall, cvOpt, refOpt, noexceptOpt) #else #define MSO_EMIT_CLRCALL(func, cvOpt, refOpt, noexceptOpt) #endif #if !defined(__clang__) && defined(_M_IX86) && !defined(_M_CEE) -#define MSO_EMIT_FASTCALL(func, cvOpt, refOpt, noexceptOpt) \ - func(__fastcall, cvOpt, refOpt, noexceptOpt) +#define MSO_EMIT_FASTCALL(func, cvOpt, refOpt, noexceptOpt) func(__fastcall, cvOpt, refOpt, noexceptOpt) #else #define MSO_EMIT_FASTCALL(func, cvOpt, refOpt, noexceptOpt) #endif #if !defined(__clang__) && defined(_M_IX86) -#define MSO_EMIT_STDCALL(func, cvOpt, refOpt, noexceptOpt) \ - func(__stdcall, cvOpt, refOpt, noexceptOpt) +#define MSO_EMIT_STDCALL(func, cvOpt, refOpt, noexceptOpt) func(__stdcall, cvOpt, refOpt, noexceptOpt) #else #define MSO_EMIT_STDCALL(func, cvOpt, refOpt, noexceptOpt) #endif -#if !defined(__clang__) \ - && ((defined(_M_IX86) && _M_IX86_FP >= 2) \ - || defined(_M_X64)) && !defined(_M_CEE) -#define MSO_EMIT_VECTORCALL(func, cvOpt, refOpt, noexceptOpt) \ - func(__vectorcall, cvOpt, refOpt, noexceptOpt) +#if !defined(__clang__) && ((defined(_M_IX86) && _M_IX86_FP >= 2) || defined(_M_X64)) && !defined(_M_CEE) +#define MSO_EMIT_VECTORCALL(func, cvOpt, refOpt, noexceptOpt) func(__vectorcall, cvOpt, refOpt, noexceptOpt) #else #define MSO_EMIT_VECTORCALL(func, cvOpt, refOpt, noexceptOpt) #endif #define MSO_NON_MEMBER_CALL(func, noexceptOpt) \ - MSO_EMIT_CDECL(func, , , noexceptOpt) \ - MSO_EMIT_CLRCALL(func, , , noexceptOpt) \ - MSO_EMIT_FASTCALL(func, , , noexceptOpt) \ - MSO_EMIT_STDCALL(func, , , noexceptOpt) \ - MSO_EMIT_VECTORCALL(func, , , noexceptOpt) + MSO_EMIT_CDECL(func, , , noexceptOpt) \ + MSO_EMIT_CLRCALL(func, , , noexceptOpt) \ + MSO_EMIT_FASTCALL(func, , , noexceptOpt) \ + MSO_EMIT_STDCALL(func, , , noexceptOpt) \ + MSO_EMIT_VECTORCALL(func, , , noexceptOpt) #if defined(__cpp_noexcept_function_type) || (_HAS_NOEXCEPT_FUNCTION_TYPES == 1) #define MSO_NON_MEMBER_CALL_NOEXCEPT(func) \ - MSO_NON_MEMBER_CALL(func, ) \ - MSO_NON_MEMBER_CALL(func, noexcept) + MSO_NON_MEMBER_CALL(func, ) \ + MSO_NON_MEMBER_CALL(func, noexcept) #else -#define MSO_NON_MEMBER_CALL_NOEXCEPT(func) \ - MSO_NON_MEMBER_CALL(func, ) +#define MSO_NON_MEMBER_CALL_NOEXCEPT(func) MSO_NON_MEMBER_CALL(func, ) #endif namespace Mso { -template class Functor; -template class FunctorThrow; +template +class Functor; +template +class FunctorThrow; //! Base interface for Mso::Functor implementation. template struct DECLSPEC_NOVTABLE IFunctor : IUnknown { - virtual TResult Invoke(TArgs&&...) noexcept = 0; + virtual TResult Invoke(TArgs&&...) noexcept = 0; }; //! Base interface for Mso::FunctorThrow implementation. template struct DECLSPEC_NOVTABLE IFunctorThrow : IUnknown { - virtual TResult Invoke(TArgs&&...) = 0; + virtual TResult Invoke(TArgs&&...) = 0; }; namespace Details { //! The library that we use for Android and Apple platforms -//! has a bug in std::is_function implementation where it does not recognize the +//! has a bug in std::is_function implementation where it does not recognize the //! functions with 'noexcept' in signature as functions. //! This code is to fix it for the non-MSVC platforms @@ -122,11 +115,11 @@ struct IsFunction : std::false_type { }; -#define MSO_IS_FUNCTION(CALL_OPT, X1, X2, NOEXCEPT_OPT) \ -template \ -struct IsFunction : std::true_type \ -{ \ -}; +#define MSO_IS_FUNCTION(CALL_OPT, X1, X2, NOEXCEPT_OPT) \ + template \ + struct IsFunction : std::true_type \ + { \ + }; MSO_NON_MEMBER_CALL_NOEXCEPT(MSO_IS_FUNCTION) #undef MSO_IS_FUNCTION @@ -134,11 +127,9 @@ MSO_NON_MEMBER_CALL_NOEXCEPT(MSO_IS_FUNCTION) template struct Decay { - using NoRefType = std::remove_reference_t; - using Type = std::conditional_t< - IsFunction::value, - std::add_pointer_t, - std::remove_cv_t>; + using NoRefType = std::remove_reference_t; + using Type = + std::conditional_t::value, std::add_pointer_t, std::remove_cv_t>; }; template @@ -162,106 +153,107 @@ using Decay_t = std::decay_t; template struct ConstexprFunctorBase : public TIFunctor { - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override { return E_FAIL; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + _Success_(return == S_OK) + STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override + { + return E_FAIL; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; //! Function object wrapper. It can be a lambda or a class implementing call operator(). template class FunctionObjectWrapper final - : public Mso::UnknownObject> + : public Mso::UnknownObject> { public: - FunctionObjectWrapper() = delete; - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctionObjectWrapper); + FunctionObjectWrapper() = delete; + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctionObjectWrapper); - template - FunctionObjectWrapper(T&& func) noexcept - : m_func(std::forward(func)) - { - } + template + FunctionObjectWrapper(T&& func) noexcept : m_func(std::forward(func)) + { + } - virtual TResult Invoke(TArgs&&... args) noexcept override - { - return m_func(std::forward(args)...); - } + virtual TResult Invoke(TArgs&&... args) noexcept override + { + return m_func(std::forward(args)...); + } private: - TFunc m_func; + TFunc m_func; }; - //! Throwing function object wrapper. It can be a lambda or a class implementing call operator(). template class FunctionObjectWrapperThrow final - : public Mso::UnknownObject> + : public Mso::UnknownObject> { public: - FunctionObjectWrapperThrow() = delete; - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctionObjectWrapperThrow); + FunctionObjectWrapperThrow() = delete; + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctionObjectWrapperThrow); - template - FunctionObjectWrapperThrow(T&& func) noexcept - : m_func(std::forward(func)) - { - } + template + FunctionObjectWrapperThrow(T&& func) noexcept : m_func(std::forward(func)) + { + } - virtual TResult Invoke(TArgs&&... args) override - { - return m_func(std::forward(args)...); - } + virtual TResult Invoke(TArgs&&... args) override + { + return m_func(std::forward(args)...); + } private: - TFunc m_func; + TFunc m_func; }; - //! Function pointer wrapper. For function pointers, we can avoid a heap allocation by making a //! static wrapper object for each function that we want to use, because we don't need to store //! per-Functor state. template -class FunctionPointerWrapper final - : public ConstexprFunctorBase> +class FunctionPointerWrapper final : public ConstexprFunctorBase> { - static_assert(std::is_pointer::value, "Must be a pointer"); - static_assert(Mso::Details::IsFunction>::value, "Must be a function pointer"); + static_assert(std::is_pointer::value, "Must be a pointer"); + static_assert(Mso::Details::IsFunction>::value, "Must be a function pointer"); public: - constexpr FunctionPointerWrapper(TFunc func) noexcept : m_func(func) {} + constexpr FunctionPointerWrapper(TFunc func) noexcept : m_func(func) {} - TResult Invoke(TArgs&&... args) noexcept override - { - return (*m_func)(std::forward(args)...); - } + TResult Invoke(TArgs&&... args) noexcept override + { + return (*m_func)(std::forward(args)...); + } private: - TFunc m_func; + TFunc m_func; }; - //! Throwing function pointer wrapper template -class FunctionPointerWrapperThrow final - : public ConstexprFunctorBase> +class FunctionPointerWrapperThrow final : public ConstexprFunctorBase> { - static_assert(std::is_pointer::value, "Must be a pointer"); - static_assert(Mso::Details::IsFunction>::value, "Must be a function pointer"); + static_assert(std::is_pointer::value, "Must be a pointer"); + static_assert(Mso::Details::IsFunction>::value, "Must be a function pointer"); public: - constexpr FunctionPointerWrapperThrow(TFunc func) noexcept : m_func(func) {} + constexpr FunctionPointerWrapperThrow(TFunc func) noexcept : m_func(func) {} - TResult Invoke(TArgs&&... args) override - { - return (*m_func)(std::forward(args)...); - } + TResult Invoke(TArgs&&... args) override + { + return (*m_func)(std::forward(args)...); + } private: - TFunc m_func; + TFunc m_func; }; - //! Stateless function wrapper. For function objects that carry no state, we //! can take a shortcut and reuse a static instance of IFunctor rather than //! allocating a new wrapper object on the heap each time. @@ -271,87 +263,95 @@ template class StatelessFunctorWrapper final : public ConstexprFunctorBase> { public: - constexpr StatelessFunctorWrapper(TFunc &func) noexcept : m_func(func) {} + constexpr StatelessFunctorWrapper(TFunc& func) noexcept : m_func(func) {} - TResult Invoke(TArgs&&... args) noexcept override - { - return m_func(std::forward(args)...); - } + TResult Invoke(TArgs&&... args) noexcept override + { + return m_func(std::forward(args)...); + } private: - TFunc &m_func; + TFunc& m_func; }; - //! Throwing stateless functor wrapper template class StatelessFunctorWrapperThrow final : public ConstexprFunctorBase> { public: - constexpr StatelessFunctorWrapperThrow(TFunc &func) noexcept : m_func(func) {} + constexpr StatelessFunctorWrapperThrow(TFunc& func) noexcept : m_func(func) {} - TResult Invoke(TArgs&&... args) override - { - return m_func(std::forward(args)...); - } + TResult Invoke(TArgs&&... args) override + { + return m_func(std::forward(args)...); + } private: - TFunc &m_func; + TFunc& m_func; }; - template TResult DoNothingFunction(TArgs...) noexcept { - return TResult(); + return TResult(); } - template struct IsFunctionObject { private: - template - static auto CheckFunctionObject(T&& t, int) - -> decltype(static_cast(std::forward(t)(std::declval()...)), std::true_type()); + template + static auto CheckFunctionObject(T&& t, int) + -> decltype(static_cast(std::forward(t)(std::declval()...)), std::true_type()); - template - static std::false_type CheckFunctionObject(T&& t, void*); + template + static std::false_type CheckFunctionObject(T&& t, void*); public: - //! IsFunctionObject is true when provided TFunc type is a function object with operator() that accepts - //! arguments of type TArgs... and its result can be converted to TResult. - constexpr static const bool Value = decltype(CheckFunctionObject(std::declval(), 0))::value; + //! IsFunctionObject is true when provided TFunc type is a function object with operator() that accepts + //! arguments of type TArgs... and its result can be converted to TResult. + constexpr static const bool Value = decltype(CheckFunctionObject(std::declval(), 0))::value; }; - //! Checks if T is an Mso::Functor -template struct IsMsoFunctor : std::false_type {}; -template struct IsMsoFunctor> : std::true_type {}; - +template +struct IsMsoFunctor : std::false_type +{ +}; +template +struct IsMsoFunctor> : std::true_type +{ +}; //! Checks if T is an Mso::FunctorThrow -template struct IsMsoFunctorThrow : std::false_type {}; -template struct IsMsoFunctorThrow> : std::true_type {}; - +template +struct IsMsoFunctorThrow : std::false_type +{ +}; +template +struct IsMsoFunctorThrow> : std::true_type +{ +}; template struct IsNoExceptFunctionObject { - constexpr static const bool Value = noexcept(std::declval()(std::declval()...)); + constexpr static const bool Value = noexcept(std::declval()(std::declval()...)); }; } // namespace Details //! Special pseudo-functor that can be passed to Mso::Functor or Mso::FunctorThrow that does nothing. //! It is more efficient than empty lambda because we do not do heap allocations in such case. -struct DoNothingFunctor {}; +struct DoNothingFunctor +{ +}; //! To indicate that function object may throw an exception and it will cause a process termination. //! Mso::Functor(std::function<>(), Mso::TerminateOnException); struct TerminateOnExceptionTag { - constexpr TerminateOnExceptionTag() noexcept {} + constexpr TerminateOnExceptionTag() noexcept {} }; constexpr const TerminateOnExceptionTag TerminateOnException; @@ -360,183 +360,175 @@ using ThrowingFunctorObjectTag = TerminateOnExceptionTag; constexpr const ThrowingFunctorObjectTag ThrowingFunctorObject; /** - Functor is a smart pointer to a IFunctor instance. - Its constructor accepts either a TCntPtr for custom implementations or a function object. - Function object is a class with a call operator(). Lambda is a function object. Function object must be noexcept. - For throwing function objects such as std::function use overload with Mso::CrashOnException value. - Functor can work with function pointers without heap allocations using FromFunctionPtr. + Functor is a smart pointer to a IFunctor instance. + Its constructor accepts either a TCntPtr for custom implementations or a function object. + Function object is a class with a call operator(). Lambda is a function object. Function object must be noexcept. + For throwing function objects such as std::function use overload with Mso::CrashOnException value. + Functor can work with function pointers without heap allocations using FromFunctionPtr. */ template class Functor { public: - using IFunctor = Mso::IFunctor; + using IFunctor = Mso::IFunctor; private: - template using EnableIfIFunctor = std::enable_if_t::value, int>; - template using EnableIfFunctionObject = std::enable_if_t< - Mso::Details::IsFunctionObject::Value - && !std::is_convertible*, IFunctor*>::value - && !Mso::Details::IsMsoFunctor>::value, int>; - template using EnableIfNoThrow = std::enable_if_t::Value, int>; - template using EnableIfThrow = std::enable_if_t::Value, int>; - template using EnableIfStateless = std::enable_if_t::value, int>; - template using EnableIfNotStateless = std::enable_if_t::value, int>; + template + using EnableIfIFunctor = std::enable_if_t::value, int>; + template + using EnableIfFunctionObject = std::enable_if_t< + Mso::Details::IsFunctionObject::Value + && !std::is_convertible*, IFunctor*>::value + && !Mso::Details::IsMsoFunctor>::value, + int>; + template + using EnableIfNoThrow = std::enable_if_t::Value, int>; + template + using EnableIfThrow = std::enable_if_t::Value, int>; + template + using EnableIfStateless = std::enable_if_t::value, int>; + template + using EnableIfNotStateless = std::enable_if_t::value, int>; public: - Functor() noexcept - { - } + Functor() noexcept {} - _Allow_implicit_ctor_ Functor(std::nullptr_t) noexcept - { - } + _Allow_implicit_ctor_ Functor(std::nullptr_t) noexcept {} - Functor(const Functor& other) noexcept - : m_impl(other.m_impl) - { - } + Functor(const Functor& other) noexcept : m_impl(other.m_impl) {} - Functor(Functor&& other) noexcept - : m_impl(std::move(other.m_impl)) - { - } + Functor(Functor&& other) noexcept : m_impl(std::move(other.m_impl)) {} - _Allow_implicit_ctor_ Functor(DoNothingFunctor) noexcept - : Functor(DoNothing()) - { - } + _Allow_implicit_ctor_ Functor(DoNothingFunctor) noexcept : Functor(DoNothing()) {} - template = 0> - _Allow_implicit_ctor_ Functor(_In_ T* impl, bool shouldAddRef = true) noexcept - : m_impl(impl, shouldAddRef) - { - } + template = 0> + _Allow_implicit_ctor_ Functor(_In_ T* impl, bool shouldAddRef = true) noexcept : m_impl(impl, shouldAddRef) + { + } - template = 0> - _Allow_implicit_ctor_ Functor(Mso::TCntPtr& impl) noexcept - : m_impl(impl) - { - } + template = 0> + _Allow_implicit_ctor_ Functor(Mso::TCntPtr& impl) noexcept : m_impl(impl) + { + } - template = 0> - _Allow_implicit_ctor_ Functor(const Mso::TCntPtr& impl) noexcept - : m_impl(impl) - { - } + template = 0> + _Allow_implicit_ctor_ Functor(const Mso::TCntPtr& impl) noexcept : m_impl(impl) + { + } - template = 0> - _Allow_implicit_ctor_ Functor(Mso::TCntPtr&& impl) noexcept - : m_impl(std::move(impl)) - { - } + template = 0> + _Allow_implicit_ctor_ Functor(Mso::TCntPtr&& impl) noexcept : m_impl(std::move(impl)) + { + } - template = 0, EnableIfNoThrow = 0, EnableIfNotStateless = 0> - _Allow_implicit_ctor_ Functor(T&& func) noexcept - : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/false) - { - } + template = 0, EnableIfNoThrow = 0, EnableIfNotStateless = 0> + _Allow_implicit_ctor_ Functor(T&& func) noexcept + : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/ false) + { + } - template = 0, EnableIfNoThrow = 0, EnableIfStateless = 0> - _Allow_implicit_ctor_ Functor(T&& func) noexcept - { - using TFunc = Mso::Details::Decay_t; - static TFunc s_func{std::forward(func)}; - static constexpr Mso::Details::StatelessFunctorWrapper s_impl{s_func}; - m_impl = Mso::TCntPtr(const_cast(static_cast(&s_impl)), /*shouldAddRef:*/ false); - } + template = 0, EnableIfNoThrow = 0, EnableIfStateless = 0> + _Allow_implicit_ctor_ Functor(T&& func) noexcept + { + using TFunc = Mso::Details::Decay_t; + static TFunc s_func{std::forward(func)}; + static constexpr Mso::Details::StatelessFunctorWrapper s_impl{s_func}; + m_impl = + Mso::TCntPtr(const_cast(static_cast(&s_impl)), /*shouldAddRef:*/ false); + } - template = 0, EnableIfThrow = 0> - _SA_deprecated_(lambda must be noexcept or use Functor constructor with TerminateOnException argument or use Mso::FunctorThrow) - Functor(T&& func) noexcept - : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/false) - { - } + template = 0, EnableIfThrow = 0> + _SA_deprecated_( + lambda must be noexcept or use Functor constructor with TerminateOnException argument or use Mso::FunctorThrow) + Functor(T&& func) noexcept + : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/ false) + { + } - //! Explicitly wraps up throwing objects such as std::function<>. - //! It should be used only in places where we cannot make function object noexcept. - template = 0> - Functor(T&& func, const Mso::TerminateOnExceptionTag&) noexcept - : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/false) - { - } + //! Explicitly wraps up throwing objects such as std::function<>. + //! It should be used only in places where we cannot make function object noexcept. + template = 0> + Functor(T&& func, const Mso::TerminateOnExceptionTag&) noexcept + : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/ false) + { + } - Functor& operator=(const Functor& other) noexcept - { - m_impl = other.m_impl; - return *this; - } + Functor& operator=(const Functor& other) noexcept + { + m_impl = other.m_impl; + return *this; + } - Functor& operator=(Functor&& other) noexcept - { - m_impl = std::move(other.m_impl); - return *this; - } + Functor& operator=(Functor&& other) noexcept + { + m_impl = std::move(other.m_impl); + return *this; + } - TResult operator()(TArgs... args) const noexcept - { - // It's important that we don't use '&&' on TArgs here. Since TArgs is a class template parameter, - // '&&' would force each argument to become an rvalue (or, subject to ref-collapsing, an lvalue ref) - // which could prevent us from being able to correctly invoke the underlying function object. With - // that said, it is important that the wrapper's 'Invoke' use '&&' to prevent a second copy of any - // non-ref-qualified parameter since a copy would already have been made here. + TResult operator()(TArgs... args) const noexcept + { + // It's important that we don't use '&&' on TArgs here. Since TArgs is a class template parameter, + // '&&' would force each argument to become an rvalue (or, subject to ref-collapsing, an lvalue ref) + // which could prevent us from being able to correctly invoke the underlying function object. With + // that said, it is important that the wrapper's 'Invoke' use '&&' to prevent a second copy of any + // non-ref-qualified parameter since a copy would already have been made here. - return m_impl->Invoke(std::forward(args)...); - } + return m_impl->Invoke(std::forward(args)...); + } - bool IsEmpty() const noexcept - { - return m_impl.IsEmpty(); - } + bool IsEmpty() const noexcept + { + return m_impl.IsEmpty(); + } - explicit operator bool() const noexcept - { - return !m_impl.IsEmpty(); - } + explicit operator bool() const noexcept + { + return !m_impl.IsEmpty(); + } - void Swap(Functor& other) noexcept - { - m_impl.Swap(other.m_impl); - } + void Swap(Functor& other) noexcept + { + m_impl.Swap(other.m_impl); + } - IFunctor* Get() const noexcept - { - return m_impl.Get(); - } + IFunctor* Get() const noexcept + { + return m_impl.Get(); + } - IFunctor* Detach() noexcept - { - return m_impl.Detach(); - } + IFunctor* Detach() noexcept + { + return m_impl.Detach(); + } - //! Wraps a function pointer in a Functor, without allocating memory. - //! Note that the function is passed as a template argument, not as a function argument. - template - static Functor FromFunctionPtr() noexcept - { - static constexpr Mso::Details::FunctionPointerWrapper s_func{func}; - return { const_cast(static_cast(&s_func)), /*shouldAddRef:*/ false }; - } + //! Wraps a function pointer in a Functor, without allocating memory. + //! Note that the function is passed as a template argument, not as a function argument. + template + static Functor FromFunctionPtr() noexcept + { + static constexpr Mso::Details::FunctionPointerWrapper s_func{func}; + return {const_cast(static_cast(&s_func)), /*shouldAddRef:*/ false}; + } - //! Returns a no-op Functor, without allocating memory. - static Functor DoNothing() noexcept - { - return FromFunctionPtr<&Mso::Details::DoNothingFunction>(); - } + //! Returns a no-op Functor, without allocating memory. + static Functor DoNothing() noexcept + { + return FromFunctionPtr<&Mso::Details::DoNothingFunction>(); + } private: - template - static IFunctor* MakeFunctionObjectWrapper(T&& func) noexcept - { - using TFunc = Mso::Details::Decay_t; - using Type = Mso::Details::FunctionObjectWrapper; - void* objMemory = Type::RefCountPolicy::Allocator::Allocate(sizeof(Type)); - VerifyAllocElseCrashTag(objMemory, 0x0131f462 /* tag_bm5r8 */); - return ::new (objMemory) Type(std::forward(func)); - } + template + static IFunctor* MakeFunctionObjectWrapper(T&& func) noexcept + { + using TFunc = Mso::Details::Decay_t; + using Type = Mso::Details::FunctionObjectWrapper; + void* objMemory = Type::RefCountPolicy::Allocator::Allocate(sizeof(Type)); + VerifyAllocElseCrashTag(objMemory, 0x0131f462 /* tag_bm5r8 */); + return ::new (objMemory) Type(std::forward(func)); + } private: - Mso::TCntPtr m_impl; + Mso::TCntPtr m_impl; }; #if defined(__cpp_noexcept_function_type) || (_HAS_NOEXCEPT_FUNCTION_TYPES == 1) @@ -547,253 +539,239 @@ template class Functor : public Functor { public: - using Functor::Functor; + using Functor::Functor; - static Functor DoNothing() noexcept - { - return Functor(DoNothingFunctor()); - } + static Functor DoNothing() noexcept + { + return Functor(DoNothingFunctor()); + } }; #endif /** - FunctorThrow is a smart pointer to a IFunctorThrow instance. - Its constructor accepts either a TCntPtr for custom implementations or a function object. - Function object is a class with a call operator(). Lambda is a function object. Function object may throw. - FunctorThrow can work with function pointers without heap allocations using FromFunctionPtr. + FunctorThrow is a smart pointer to a IFunctorThrow instance. + Its constructor accepts either a TCntPtr for custom implementations or a function object. + Function object is a class with a call operator(). Lambda is a function object. Function object may throw. + FunctorThrow can work with function pointers without heap allocations using FromFunctionPtr. */ template class FunctorThrow { public: - using IFunctorThrow = Mso::IFunctorThrow; + using IFunctorThrow = Mso::IFunctorThrow; private: - template using EnableIfIFunctorThrow = std::enable_if_t::value, int>; - template using EnableIfFunctionObject = std::enable_if_t< - Mso::Details::IsFunctionObject::Value - && !std::is_convertible*, IFunctorThrow*>::value - && !Mso::Details::IsMsoFunctorThrow>::value, int>; - template using EnableIfStateless = std::enable_if_t::value, int>; - template using EnableIfNotStateless = std::enable_if_t::value, int>; + template + using EnableIfIFunctorThrow = std::enable_if_t::value, int>; + template + using EnableIfFunctionObject = std::enable_if_t< + Mso::Details::IsFunctionObject::Value + && !std::is_convertible*, IFunctorThrow*>::value + && !Mso::Details::IsMsoFunctorThrow>::value, + int>; + template + using EnableIfStateless = std::enable_if_t::value, int>; + template + using EnableIfNotStateless = std::enable_if_t::value, int>; public: - FunctorThrow() noexcept - { - } + FunctorThrow() noexcept {} - _Allow_implicit_ctor_ FunctorThrow(std::nullptr_t) noexcept - { - } + _Allow_implicit_ctor_ FunctorThrow(std::nullptr_t) noexcept {} - FunctorThrow(const FunctorThrow& other) noexcept - : m_impl(other.m_impl) - { - } + FunctorThrow(const FunctorThrow& other) noexcept : m_impl(other.m_impl) {} - FunctorThrow(FunctorThrow&& other) noexcept - : m_impl(std::move(other.m_impl)) - { - } + FunctorThrow(FunctorThrow&& other) noexcept : m_impl(std::move(other.m_impl)) {} - _Allow_implicit_ctor_ FunctorThrow(DoNothingFunctor) noexcept - : FunctorThrow(DoNothing()) - { - } + _Allow_implicit_ctor_ FunctorThrow(DoNothingFunctor) noexcept : FunctorThrow(DoNothing()) {} - template = 0> - _Allow_implicit_ctor_ FunctorThrow(_In_ T* impl, bool shouldAddRef = true) noexcept - : m_impl(impl, shouldAddRef) - { - } + template = 0> + _Allow_implicit_ctor_ FunctorThrow(_In_ T* impl, bool shouldAddRef = true) noexcept : m_impl(impl, shouldAddRef) + { + } - template = 0> - _Allow_implicit_ctor_ FunctorThrow(Mso::TCntPtr& impl) noexcept - : m_impl(impl) - { - } + template = 0> + _Allow_implicit_ctor_ FunctorThrow(Mso::TCntPtr& impl) noexcept : m_impl(impl) + { + } - template = 0> - _Allow_implicit_ctor_ FunctorThrow(const Mso::TCntPtr& impl) noexcept - : m_impl(impl) - { - } + template = 0> + _Allow_implicit_ctor_ FunctorThrow(const Mso::TCntPtr& impl) noexcept : m_impl(impl) + { + } - template = 0> - _Allow_implicit_ctor_ FunctorThrow(Mso::TCntPtr&& impl) noexcept - : m_impl(std::move(impl)) - { - } + template = 0> + _Allow_implicit_ctor_ FunctorThrow(Mso::TCntPtr&& impl) noexcept : m_impl(std::move(impl)) + { + } - template = 0, EnableIfNotStateless = 0> - _Allow_implicit_ctor_ FunctorThrow(T&& func) noexcept - : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/false) - { - } + template = 0, EnableIfNotStateless = 0> + _Allow_implicit_ctor_ FunctorThrow(T&& func) noexcept + : m_impl(MakeFunctionObjectWrapper(std::forward(func)), /*fDoAddRef:*/ false) + { + } - template = 0, EnableIfStateless = 0> - _Allow_implicit_ctor_ FunctorThrow(T&& func) noexcept - { - using TFunc = Mso::Details::Decay_t; - static TFunc s_func{std::forward(func)}; - static constexpr Mso::Details::StatelessFunctorWrapperThrow s_impl{s_func}; - m_impl = Mso::TCntPtr(const_cast(static_cast(&s_impl)), /*shouldAddRef:*/ false); - } + template = 0, EnableIfStateless = 0> + _Allow_implicit_ctor_ FunctorThrow(T&& func) noexcept + { + using TFunc = Mso::Details::Decay_t; + static TFunc s_func{std::forward(func)}; + static constexpr Mso::Details::StatelessFunctorWrapperThrow s_impl{s_func}; + m_impl = Mso::TCntPtr( + const_cast(static_cast(&s_impl)), /*shouldAddRef:*/ false); + } - FunctorThrow& operator=(const FunctorThrow& other) noexcept - { - m_impl = other.m_impl; - return *this; - } + FunctorThrow& operator=(const FunctorThrow& other) noexcept + { + m_impl = other.m_impl; + return *this; + } - FunctorThrow& operator=(FunctorThrow&& other) noexcept - { - m_impl = std::move(other.m_impl); - return *this; - } + FunctorThrow& operator=(FunctorThrow&& other) noexcept + { + m_impl = std::move(other.m_impl); + return *this; + } - TResult operator()(TArgs... args) const - { - // It's important that we don't use '&&' on TArgs here. Since TArgs is a class template parameter, - // '&&' would force each argument to become an rvalue (or, subject to ref-collapsing, an lvalue ref) - // which could prevent us from being able to correctly invoke the underlying function object. With - // that said, it is important that the wrapper's 'Invoke' use '&&' to prevent a second copy of any - // non-ref-qualified parameter since a copy would already have been made here. + TResult operator()(TArgs... args) const + { + // It's important that we don't use '&&' on TArgs here. Since TArgs is a class template parameter, + // '&&' would force each argument to become an rvalue (or, subject to ref-collapsing, an lvalue ref) + // which could prevent us from being able to correctly invoke the underlying function object. With + // that said, it is important that the wrapper's 'Invoke' use '&&' to prevent a second copy of any + // non-ref-qualified parameter since a copy would already have been made here. - return m_impl->Invoke(std::forward(args)...); - } + return m_impl->Invoke(std::forward(args)...); + } - bool IsEmpty() const noexcept - { - return m_impl.IsEmpty(); - } + bool IsEmpty() const noexcept + { + return m_impl.IsEmpty(); + } - explicit operator bool() const noexcept - { - return !m_impl.IsEmpty(); - } + explicit operator bool() const noexcept + { + return !m_impl.IsEmpty(); + } - void Swap(FunctorThrow& other) noexcept - { - m_impl.Swap(other.m_impl); - } + void Swap(FunctorThrow& other) noexcept + { + m_impl.Swap(other.m_impl); + } - IFunctorThrow* Get() const noexcept - { - return m_impl.Get(); - } + IFunctorThrow* Get() const noexcept + { + return m_impl.Get(); + } - IFunctorThrow* Detach() noexcept - { - return m_impl.Detach(); - } + IFunctorThrow* Detach() noexcept + { + return m_impl.Detach(); + } - //! Wraps a function pointer in a FunctorThrow, without allocating memory. - //! Note that the function is passed as a template argument, not as a function argument. - template - static FunctorThrow FromFunctionPtr() noexcept - { - static constexpr Mso::Details::FunctionPointerWrapperThrow s_func { func }; - return { const_cast(static_cast(&s_func)), /*shouldAddRef:*/ false }; - } + //! Wraps a function pointer in a FunctorThrow, without allocating memory. + //! Note that the function is passed as a template argument, not as a function argument. + template + static FunctorThrow FromFunctionPtr() noexcept + { + static constexpr Mso::Details::FunctionPointerWrapperThrow s_func{func}; + return {const_cast(static_cast(&s_func)), /*shouldAddRef:*/ false}; + } - //! Returns a no-op FunctorThrow, without allocating memory. - static FunctorThrow DoNothing() noexcept - { - return FromFunctionPtr<&Mso::Details::DoNothingFunction>(); - } + //! Returns a no-op FunctorThrow, without allocating memory. + static FunctorThrow DoNothing() noexcept + { + return FromFunctionPtr<&Mso::Details::DoNothingFunction>(); + } private: - template - static IFunctorThrow* MakeFunctionObjectWrapper(T&& func) noexcept - { - using TFunc = Mso::Details::Decay_t; - using Type = Mso::Details::FunctionObjectWrapperThrow; - void* objMemory = Type::RefCountPolicy::Allocator::Allocate(sizeof(Type)); - VerifyAllocElseCrashTag(objMemory, 0x0131f463 /* tag_bm5r9 */); - return ::new (objMemory) Type(std::forward(func)); - } + template + static IFunctorThrow* MakeFunctionObjectWrapper(T&& func) noexcept + { + using TFunc = Mso::Details::Decay_t; + using Type = Mso::Details::FunctionObjectWrapperThrow; + void* objMemory = Type::RefCountPolicy::Allocator::Allocate(sizeof(Type)); + VerifyAllocElseCrashTag(objMemory, 0x0131f463 /* tag_bm5r9 */); + return ::new (objMemory) Type(std::forward(func)); + } private: - Mso::TCntPtr m_impl; + Mso::TCntPtr m_impl; }; - template inline bool operator==(const Functor& left, const Functor& right) noexcept { - return left.Get() == right.Get(); + return left.Get() == right.Get(); } template inline bool operator==(std::nullptr_t, const Functor& right) noexcept { - return nullptr == right.Get(); + return nullptr == right.Get(); } template inline bool operator==(const Functor& left, std::nullptr_t) noexcept { - return left.Get() == nullptr; + return left.Get() == nullptr; } template inline bool operator!=(const Functor& left, const Functor& right) noexcept { - return left.Get() != right.Get(); + return left.Get() != right.Get(); } template inline bool operator!=(std::nullptr_t, const Functor& right) noexcept { - return nullptr != right.Get(); + return nullptr != right.Get(); } template inline bool operator!=(const Functor& left, std::nullptr_t) noexcept { - return left.Get() != nullptr; + return left.Get() != nullptr; } - template inline bool operator==(const FunctorThrow& left, const FunctorThrow& right) noexcept { - return left.Get() == right.Get(); + return left.Get() == right.Get(); } template inline bool operator==(std::nullptr_t, const FunctorThrow& right) noexcept { - return nullptr == right.Get(); + return nullptr == right.Get(); } template inline bool operator==(const FunctorThrow& left, std::nullptr_t) noexcept { - return left.Get() == nullptr; + return left.Get() == nullptr; } template inline bool operator!=(const FunctorThrow& left, const FunctorThrow& right) noexcept { - return left.Get() != right.Get(); + return left.Get() != right.Get(); } template inline bool operator!=(std::nullptr_t, const FunctorThrow& right) noexcept { - return nullptr != right.Get(); + return nullptr != right.Get(); } template inline bool operator!=(const FunctorThrow& left, std::nullptr_t) noexcept { - return left.Get() != nullptr; + return left.Get() != nullptr; } - // Aliases for the most common function object type "void()". using IVoidFunctor = IFunctor; using VoidFunctor = Functor; @@ -805,20 +783,19 @@ using VoidFunctorThrowImpl = Mso::UnknownObject inline void swap(Mso::Functor& left, Mso::Functor& right) noexcept { - left.Swap(right); + left.Swap(right); } template inline void swap(Mso::FunctorThrow& left, Mso::FunctorThrow& right) noexcept { - left.Swap(right); + left.Swap(right); } } // namespace std diff --git a/libs/functional/include/functional/functorRef.h b/libs/functional/include/functional/functorRef.h index d2cf8cd..1e6f131 100644 --- a/libs/functional/include/functional/functorRef.h +++ b/libs/functional/include/functional/functorRef.h @@ -17,7 +17,7 @@ //! stored as a field in an object. //! //! Mso::FunctorRef has the following semantics: -//! +//! //! - Only keeps a reference to the function object. //! - Never copies or moves the provided function object. //! - Does not do a heap allocation and has size of two pointers (one is @@ -29,10 +29,10 @@ //! unlike std::function<>. //! - Supports optional semantic by allowing to be initialized with nullptr, and //! then to be checked for non-null by the explicit bool operator. -//! +//! //! The Mso::FunctorRef only supports noexcept function objects. //! Use Mso::FunctorRefThrow for throwing function objects. -//! +//! //! In case if you want to store function object or transfer its ownership, you can use: //! - Mso::Functor that is an Mso::TCntPtr to a ref counted heap-allocated object. //! - Mso::SmallFunctor that uses in-place storage. @@ -45,7 +45,7 @@ //! virtual MyObject FindInCache(const Mso::FunctorRef& predicate) = 0; //! //! This method can be called as following: -//! +//! //! myCache->FindInCache([this](MyObject& obj) noexcept { return this->CheckObj(obj); }); //! //! Note that we can simply pass lambda as a parameter because we allow use of @@ -115,91 +115,91 @@ using FunctorRefStorage = std::aligned_storage::type; } // namespace Details - //! Reference to a non-throwing function object. +//! Reference to a non-throwing function object. template class FunctorRef #if !defined(__cpp_noexcept_function_type) && (_HAS_NOEXCEPT_FUNCTION_TYPES != 1) -final + final #endif { public: - //! Creates an empty FunctorRef - _Allow_implicit_ctor_ FunctorRef(std::nullptr_t) noexcept - { - } + //! Creates an empty FunctorRef + _Allow_implicit_ctor_ FunctorRef(std::nullptr_t) noexcept {} - //! Creates a non-empty FunctorRef - template - _Allow_implicit_ctor_ FunctorRef(T&& func) noexcept - { - using WrapperType = FunctorRefWrapper>; + //! Creates a non-empty FunctorRef + template + _Allow_implicit_ctor_ FunctorRef(T&& func) noexcept + { + using WrapperType = FunctorRefWrapper>; - // Make sure that WrapperType storage requirements match the FunctorRefStorage. - static_assert(sizeof(WrapperType) <= sizeof(Details::FunctorRefStorage), - "WrapperType is too big to fit in FunctorRefStorage."); - static_assert(std::alignment_of::value <= std::alignment_of::value, - "WrapperType alignment does not match to FunctorRefStorage."); + // Make sure that WrapperType storage requirements match the FunctorRefStorage. + static_assert( + sizeof(WrapperType) <= sizeof(Details::FunctorRefStorage), + "WrapperType is too big to fit in FunctorRefStorage."); + static_assert( + std::alignment_of::value <= std::alignment_of::value, + "WrapperType alignment does not match to FunctorRefStorage."); - ::new (std::addressof(m_storage)) WrapperType{&func}; - } + ::new (std::addressof(m_storage)) WrapperType{&func}; + } - //! Delete copy and move constructors and assignment operators. - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRef); + //! Delete copy and move constructors and assignment operators. + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRef); - //! Calls referenced function object. - //! Crash if referenced function object is nullptr. - TResult operator()(TArgs... args) const noexcept - { - // It's important that we don't use '&&' on TArgs here. Since TArgs is a class - // template parameter, the '&&' would force each argument to become an rvalue - // (or, subject to ref-collapsing, an lvalue ref) which could prevent us from - // being able to correctly invoke the underlying function object. With - // that said, it is important that the wrapper's 'Invoke' uses '&&' to prevent - // a second copy of any non-ref-qualified parameter since a copy would already - // have been made here. + //! Calls referenced function object. + //! Crash if referenced function object is nullptr. + TResult operator()(TArgs... args) const noexcept + { + // It's important that we don't use '&&' on TArgs here. Since TArgs is a class + // template parameter, the '&&' would force each argument to become an rvalue + // (or, subject to ref-collapsing, an lvalue ref) which could prevent us from + // being able to correctly invoke the underlying function object. With + // that said, it is important that the wrapper's 'Invoke' uses '&&' to prevent + // a second copy of any non-ref-qualified parameter since a copy would already + // have been made here. - VerifyElseCrashSzTag(*this, "FunctorRef must not be empty", 0x025d9804 /* tag_cxz6e */); - return reinterpret_cast(std::addressof(m_storage))->Invoke(std::forward(args)...); - } + VerifyElseCrashSzTag(*this, "FunctorRef must not be empty", 0x025d9804 /* tag_cxz6e */); + return reinterpret_cast(std::addressof(m_storage))->Invoke(std::forward(args)...); + } - //! True if wrapped function object is not nullptr. - explicit operator bool() const noexcept - { - return *reinterpret_cast(std::addressof(m_storage)) != 0; - } + //! True if wrapped function object is not nullptr. + explicit operator bool() const noexcept + { + return *reinterpret_cast(std::addressof(m_storage)) != 0; + } private: - //! The interface to be implemented by FunctorRefWrapper. - struct IFunctorRef - { - virtual TResult Invoke(TArgs&&...) const noexcept = 0; - }; + //! The interface to be implemented by FunctorRefWrapper. + struct IFunctorRef + { + virtual TResult Invoke(TArgs&&...) const noexcept = 0; + }; - //! A wrapper for a function object reference. - //! We do not call destructor for this class because it does not need to free any resources. - template - struct FunctorRefWrapper final : IFunctorRef - { - FunctorRefWrapper(T* func) noexcept : m_func(func) {} - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRefWrapper); - ~FunctorRefWrapper() = delete; + //! A wrapper for a function object reference. + //! We do not call destructor for this class because it does not need to free any resources. + template + struct FunctorRefWrapper final : IFunctorRef + { + FunctorRefWrapper(T* func) noexcept : m_func(func) {} + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRefWrapper); + ~FunctorRefWrapper() = delete; - TResult Invoke(TArgs&&... args) const noexcept override - { - // If you see OACR warning "Nothrow Func Throws" here then it means that the - // provided lambda or function object's operator() are not marked as noexcept. + TResult Invoke(TArgs&&... args) const noexcept override + { + // If you see OACR warning "Nothrow Func Throws" here then it means that the + // provided lambda or function object's operator() are not marked as noexcept. - // We use const_cast to enable support for mutable lambdas - return (*const_cast(this)->m_func)(std::forward(args)...); - } + // We use const_cast to enable support for mutable lambdas + return (*const_cast(this)->m_func)(std::forward(args)...); + } - private: - T* m_func; - }; + private: + T* m_func; + }; private: - // Storage for 2 pointers: v_table + reference - Details::FunctorRefStorage m_storage { 0 }; + // Storage for 2 pointers: v_table + reference + Details::FunctorRefStorage m_storage{0}; }; #if defined(__cpp_noexcept_function_type) || (_HAS_NOEXCEPT_FUNCTION_TYPES == 1) @@ -210,7 +210,7 @@ template class FunctorRef : public FunctorRef { public: - using FunctorRef::FunctorRef; + using FunctorRef::FunctorRef; }; #endif @@ -220,88 +220,88 @@ template class FunctorRefThrow final { public: - //! Creates an empty FunctorRefThrow - _Allow_implicit_ctor_ FunctorRefThrow(std::nullptr_t) noexcept - { - } + //! Creates an empty FunctorRefThrow + _Allow_implicit_ctor_ FunctorRefThrow(std::nullptr_t) noexcept {} - //! Creates an non-empty FunctorRefThrow - template - _Allow_implicit_ctor_ FunctorRefThrow(T&& func) noexcept - { - using WrapperType = FunctorRefThrowWrapper>; + //! Creates an non-empty FunctorRefThrow + template + _Allow_implicit_ctor_ FunctorRefThrow(T&& func) noexcept + { + using WrapperType = FunctorRefThrowWrapper>; - // Make sure that WrapperType storage requirements match the FunctorRefStorage. - static_assert(sizeof(WrapperType) <= sizeof(Details::FunctorRefStorage), - "WrapperType is too big to fit in FunctorRefStorage."); - static_assert(std::alignment_of::value <= std::alignment_of::value, - "WrapperType alignment does not match to FunctorRefStorage."); + // Make sure that WrapperType storage requirements match the FunctorRefStorage. + static_assert( + sizeof(WrapperType) <= sizeof(Details::FunctorRefStorage), + "WrapperType is too big to fit in FunctorRefStorage."); + static_assert( + std::alignment_of::value <= std::alignment_of::value, + "WrapperType alignment does not match to FunctorRefStorage."); - ::new (std::addressof(m_storage)) WrapperType{&func}; - } + ::new (std::addressof(m_storage)) WrapperType{&func}; + } - //! Delete copy and move constructors and assignment operators. - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRefThrow); + //! Delete copy and move constructors and assignment operators. + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRefThrow); - //! Calls referenced function object. - //! Crash if referenced function object is nullptr. - TResult operator()(TArgs... args) const - { - // It's important that we don't use '&&' on TArgs here. Since TArgs is a class - // template parameter, the '&&' would force each argument to become an rvalue - // (or, subject to ref-collapsing, an lvalue ref) which could prevent us from - // being able to correctly invoke the underlying function object. With - // that said, it is important that the wrapper's 'Invoke' uses '&&' to prevent - // a second copy of any non-ref-qualified parameter since a copy would already - // have been made here. + //! Calls referenced function object. + //! Crash if referenced function object is nullptr. + TResult operator()(TArgs... args) const + { + // It's important that we don't use '&&' on TArgs here. Since TArgs is a class + // template parameter, the '&&' would force each argument to become an rvalue + // (or, subject to ref-collapsing, an lvalue ref) which could prevent us from + // being able to correctly invoke the underlying function object. With + // that said, it is important that the wrapper's 'Invoke' uses '&&' to prevent + // a second copy of any non-ref-qualified parameter since a copy would already + // have been made here. - VerifyElseCrashSzTag(*this, "FunctorRefThrow must not be empty", 0x025d9805 /* tag_cxz6f */); - return reinterpret_cast(std::addressof(m_storage))->Invoke(std::forward(args)...); - } + VerifyElseCrashSzTag(*this, "FunctorRefThrow must not be empty", 0x025d9805 /* tag_cxz6f */); + return reinterpret_cast(std::addressof(m_storage))->Invoke(std::forward(args)...); + } - //! True if wrapped function object is not nullptr. - explicit operator bool() const noexcept - { - return *reinterpret_cast(std::addressof(m_storage)) != 0; - } + //! True if wrapped function object is not nullptr. + explicit operator bool() const noexcept + { + return *reinterpret_cast(std::addressof(m_storage)) != 0; + } private: - //! The interface to be implemented by FunctorRefThrowWrapper. - struct IFunctorRefThrow - { - virtual TResult Invoke(TArgs&&...) const = 0; - }; + //! The interface to be implemented by FunctorRefThrowWrapper. + struct IFunctorRefThrow + { + virtual TResult Invoke(TArgs&&...) const = 0; + }; - //! A wrapper for a function object reference. - //! We do not call destructor for this class because it does not need to free any resources. - template - struct FunctorRefThrowWrapper final : IFunctorRefThrow - { - FunctorRefThrowWrapper(T* func) noexcept : m_func(func) {} - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRefThrowWrapper); - ~FunctorRefThrowWrapper() = delete; + //! A wrapper for a function object reference. + //! We do not call destructor for this class because it does not need to free any resources. + template + struct FunctorRefThrowWrapper final : IFunctorRefThrow + { + FunctorRefThrowWrapper(T* func) noexcept : m_func(func) {} + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FunctorRefThrowWrapper); + ~FunctorRefThrowWrapper() = delete; - TResult Invoke(TArgs&&... args) const override - { - OACR_POSSIBLE_THROW; - // We use const_cast to enable support for mutable lambdas - return (*const_cast(this)->m_func)(std::forward(args)...); - } + TResult Invoke(TArgs&&... args) const override + { + OACR_POSSIBLE_THROW; + // We use const_cast to enable support for mutable lambdas + return (*const_cast(this)->m_func)(std::forward(args)...); + } - private: - T* m_func; - }; + private: + T* m_func; + }; private: - // Storage for 2 pointers: v_table + reference - Details::FunctorRefStorage m_storage { 0 }; + // Storage for 2 pointers: v_table + reference + Details::FunctorRefStorage m_storage{0}; }; /// Aliases for the most common function object type "void()". using VoidFunctorRef = FunctorRef; using VoidFunctorRefThrow = FunctorRefThrow; -} +} // namespace Mso #pragma pop_macro("new") diff --git a/libs/functional/tests/functorRefTest.cpp b/libs/functional/tests/functorRefTest.cpp index 677f314..b6153e5 100644 --- a/libs/functional/tests/functorRefTest.cpp +++ b/libs/functional/tests/functorRefTest.cpp @@ -16,353 +16,370 @@ Unit tests for classes in the Functor.h namespace { struct MyParam { - void AddRef() const { ++AddRefCount; } - void Release() const { UNREFERENCED_OACR(this); /* Do not decrement */ } - mutable int AddRefCount = 0; // AddRef() call count - int Value; + void AddRef() const + { + ++AddRefCount; + } + void Release() const + { + UNREFERENCED_OACR(this); /* Do not decrement */ + } + mutable int AddRefCount = 0; // AddRef() call count + int Value; }; -} +} // namespace struct TestClass { - static void Execute(const Mso::VoidFunctorRef& func) noexcept - { - func(); - } + static void Execute(const Mso::VoidFunctorRef& func) noexcept + { + func(); + } - static void ExecuteThrow(const Mso::VoidFunctorRefThrow& func) - { - func(); - } + static void ExecuteThrow(const Mso::VoidFunctorRefThrow& func) + { + func(); + } - static void ExecuteNullable(const Mso::VoidFunctorRef& func) noexcept - { - if (func) - { - func(); - } - } + static void ExecuteNullable(const Mso::VoidFunctorRef& func) noexcept + { + if (func) + { + func(); + } + } - static void ExecuteNullableThrow(const Mso::VoidFunctorRefThrow& func) - { - if (func) - { - func(); - } - } + static void ExecuteNullableThrow(const Mso::VoidFunctorRefThrow& func) + { + if (func) + { + func(); + } + } - static int Aggregate(int x, int y, const Mso::FunctorRef& func) noexcept - { - return func(x, y); - } + static int Aggregate(int x, int y, const Mso::FunctorRef& func) noexcept + { + return func(x, y); + } - static int AggregateThrow(int x, int y, const Mso::FunctorRefThrow& func) - { - return func(x, y); - } + static int AggregateThrow(int x, int y, const Mso::FunctorRefThrow& func) + { + return func(x, y); + } - static int PassByRef(const Mso::TCntPtr& p, const Mso::FunctorRef&)>& func) noexcept - { - return func(p); - } + static int PassByRef( + const Mso::TCntPtr& p, + const Mso::FunctorRef&)>& func) noexcept + { + return func(p); + } - static int PassByRefThrow(const Mso::TCntPtr& p, const Mso::FunctorRefThrow&)>& func) - { - return func(p); - } + static int PassByRefThrow( + const Mso::TCntPtr& p, + const Mso::FunctorRefThrow&)>& func) + { + return func(p); + } - static Mso::TCntPtr PassAsRValue(Mso::TCntPtr&& p, const Mso::FunctorRef(Mso::TCntPtr&&)>& func) noexcept - { - return func(std::move(p)); - } + static Mso::TCntPtr PassAsRValue( + Mso::TCntPtr&& p, + const Mso::FunctorRef(Mso::TCntPtr&&)>& func) noexcept + { + return func(std::move(p)); + } - static Mso::TCntPtr PassAsRValueThrow(Mso::TCntPtr&& p, const Mso::FunctorRefThrow(Mso::TCntPtr&&)>& func) - { - return func(std::move(p)); - } + static Mso::TCntPtr PassAsRValueThrow( + Mso::TCntPtr&& p, + const Mso::FunctorRefThrow(Mso::TCntPtr&&)>& func) + { + return func(std::move(p)); + } -OACR_WARNING_PUSH -OACR_WARNING_DISABLE(BY_VALUE_TEMPLATEFORMAL_WITH_DTOR, "We want to test that we can pass by value") + OACR_WARNING_PUSH + OACR_WARNING_DISABLE(BY_VALUE_TEMPLATEFORMAL_WITH_DTOR, "We want to test that we can pass by value") - static std::unique_ptr PassByValue(std::unique_ptr p, const Mso::FunctorRef(std::unique_ptr)>& func) noexcept - { - return func(std::move(p)); - } + static std::unique_ptr PassByValue( + std::unique_ptr p, + const Mso::FunctorRef(std::unique_ptr)>& func) noexcept + { + return func(std::move(p)); + } - static std::unique_ptr PassByValueThrow(std::unique_ptr p, const Mso::FunctorRefThrow(std::unique_ptr)>& func) - { - return func(std::move(p)); - } + static std::unique_ptr PassByValueThrow( + std::unique_ptr p, + const Mso::FunctorRefThrow(std::unique_ptr)>& func) + { + return func(std::move(p)); + } -OACR_WARNING_POP + OACR_WARNING_POP }; struct TestClassNoexcept { - static void Execute(const Mso::FunctorRef& func) noexcept - { - func(); - } + static void Execute(const Mso::FunctorRef& func) noexcept + { + func(); + } - static int Aggregate(int x, int y, const Mso::FunctorRef& func) noexcept - { - return func(x, y); - } + static int Aggregate(int x, int y, const Mso::FunctorRef& func) noexcept + { + return func(x, y); + } - static int PassByRef(const Mso::TCntPtr& p, const Mso::FunctorRef&) noexcept>& func) noexcept - { - return func(p); - } + static int PassByRef( + const Mso::TCntPtr& p, + const Mso::FunctorRef&) noexcept>& func) noexcept + { + return func(p); + } - static Mso::TCntPtr PassAsRValue(Mso::TCntPtr&& p, const Mso::FunctorRef(Mso::TCntPtr&&) noexcept>& func) noexcept - { - return func(std::move(p)); - } + static Mso::TCntPtr PassAsRValue( + Mso::TCntPtr&& p, + const Mso::FunctorRef(Mso::TCntPtr&&) noexcept>& func) noexcept + { + return func(std::move(p)); + } }; -TEST_CLASS(FunctorRefTest) +TEST_CLASS (FunctorRefTest) { - TEST_METHOD(FunctorRef_Lambda) - { - bool isCalled = false; - TestClass::Execute([&isCalled]() noexcept { isCalled = true; }); - TestCheck(isCalled); - } + TEST_METHOD(FunctorRef_Lambda) + { + bool isCalled = false; + TestClass::Execute([&isCalled]() noexcept { isCalled = true; }); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRefThrow_Lambda) - { - bool isCalled = false; - TestClass::ExecuteThrow([&isCalled]() noexcept { isCalled = true; }); - TestCheck(isCalled); - } + TEST_METHOD(FunctorRefThrow_Lambda) + { + bool isCalled = false; + TestClass::ExecuteThrow([&isCalled]() noexcept { isCalled = true; }); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRef_Lambda2) - { - bool isCalled = false; - auto lambda = [&isCalled]() noexcept { isCalled = true; }; - TestClass::Execute(lambda); - TestCheck(isCalled); - } + TEST_METHOD(FunctorRef_Lambda2) + { + bool isCalled = false; + auto lambda = [&isCalled]() noexcept { isCalled = true; }; + TestClass::Execute(lambda); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRefThrow_Lambda2) - { - bool isCalled = false; - auto lambda = [&isCalled]() noexcept { isCalled = true; }; - TestClass::ExecuteThrow(lambda); - TestCheck(isCalled); - } + TEST_METHOD(FunctorRefThrow_Lambda2) + { + bool isCalled = false; + auto lambda = [&isCalled]() noexcept { isCalled = true; }; + TestClass::ExecuteThrow(lambda); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRef_Nullable) - { - TestClass::ExecuteNullable(nullptr); + TEST_METHOD(FunctorRef_Nullable) + { + TestClass::ExecuteNullable(nullptr); - bool isCalled = false; - TestClass::ExecuteNullable([&isCalled]() noexcept { isCalled = true; }); - TestCheck(isCalled); - } + bool isCalled = false; + TestClass::ExecuteNullable([&isCalled]() noexcept { isCalled = true; }); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRefThrow_Nullable) - { - TestClass::ExecuteNullableThrow(nullptr); + TEST_METHOD(FunctorRefThrow_Nullable) + { + TestClass::ExecuteNullableThrow(nullptr); - bool isCalled = false; - TestClass::ExecuteNullableThrow([&isCalled]() noexcept { isCalled = true; }); - TestCheck(isCalled); - } + bool isCalled = false; + TestClass::ExecuteNullableThrow([&isCalled]() noexcept { isCalled = true; }); + TestCheck(isCalled); + } - TESTMETHOD_REQUIRES_SEH(FunctorRef_Nullable_Crash) - { - TestCheckCrash(TestClass::Execute(nullptr)); - } + TESTMETHOD_REQUIRES_SEH(FunctorRef_Nullable_Crash) + { + TestCheckCrash(TestClass::Execute(nullptr)); + } - TESTMETHOD_REQUIRES_SEH(FunctorRefThrow_Nullable_Crash) - { - TestCheckCrash(TestClass::ExecuteThrow(nullptr)); - } + TESTMETHOD_REQUIRES_SEH(FunctorRefThrow_Nullable_Crash) + { + TestCheckCrash(TestClass::ExecuteThrow(nullptr)); + } - TEST_METHOD(FunctorRef_MsoFunctor) - { - // It can be useful in case when we have an std::function available. - bool isCalled = false; - auto func = Mso::VoidFunctor([&isCalled]() noexcept { isCalled = true; }); - TestClass::Execute(func); - TestCheck(isCalled); - } + TEST_METHOD(FunctorRef_MsoFunctor) + { + // It can be useful in case when we have an std::function available. + bool isCalled = false; + auto func = Mso::VoidFunctor([&isCalled]() noexcept { isCalled = true; }); + TestClass::Execute(func); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRef_LambdaReturnValue) - { - int addResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x + y; }); - TestCheckEqual(8, addResult); + TEST_METHOD(FunctorRef_LambdaReturnValue) + { + int addResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x + y; }); + TestCheckEqual(8, addResult); - int multResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x * y; }); - TestCheckEqual(15, multResult); - } + int multResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x * y; }); + TestCheckEqual(15, multResult); + } - TEST_METHOD(FunctorRef_LambdaPassParamByRef) - { - // Pass an Mso::TCntPtr as an const reference and see that it was never called AddRef() - MyParam param; - auto spParam = Mso::TCntPtr(¶m); - TestCheckEqual(1, param.AddRefCount); - param.Value = 10; + TEST_METHOD(FunctorRef_LambdaPassParamByRef) + { + // Pass an Mso::TCntPtr as an const reference and see that it was never called AddRef() + MyParam param; + auto spParam = Mso::TCntPtr(¶m); + TestCheckEqual(1, param.AddRefCount); + param.Value = 10; - int result = TestClass::PassByRef(spParam, [](const Mso::TCntPtr& p) noexcept { return p->Value; }); - TestCheckEqual(10, result); - TestCheckEqual(1, param.AddRefCount); - } + int result = TestClass::PassByRef(spParam, [](const Mso::TCntPtr& p) noexcept { return p->Value; }); + TestCheckEqual(10, result); + TestCheckEqual(1, param.AddRefCount); + } - TEST_METHOD(FunctorRef_LambdaPassParamAsRValue) - { - // Pass an Mso::TCntPtr as an r-value and see that it was never called AddRef() - MyParam param; - auto spParam = Mso::TCntPtr(¶m); - TestCheckEqual(1, param.AddRefCount); - - auto spParam2 = TestClass::PassAsRValue(std::move(spParam), [](Mso::TCntPtr&& p) noexcept { return std::move(p); }); - TestCheckEqual(1, param.AddRefCount); - } + TEST_METHOD(FunctorRef_LambdaPassParamAsRValue) + { + // Pass an Mso::TCntPtr as an r-value and see that it was never called AddRef() + MyParam param; + auto spParam = Mso::TCntPtr(¶m); + TestCheckEqual(1, param.AddRefCount); - TEST_METHOD(FunctorRef_noexcept_Lambda) - { - bool isCalled = false; - TestClass::Execute([&isCalled]() noexcept { isCalled = true; }); - TestCheck(isCalled); - } + auto spParam2 = + TestClass::PassAsRValue(std::move(spParam), [](Mso::TCntPtr&& p) noexcept { return std::move(p); }); + TestCheckEqual(1, param.AddRefCount); + } - TEST_METHOD(FunctorRef_noexcept_MsoFunctor) - { - // It can be useful in case when we have an std::function available. - bool isCalled = false; - auto func = Mso::VoidFunctor([&isCalled]() noexcept { isCalled = true; }); - TestClass::Execute(func); - TestCheck(isCalled); - } + TEST_METHOD(FunctorRef_noexcept_Lambda) + { + bool isCalled = false; + TestClass::Execute([&isCalled]() noexcept { isCalled = true; }); + TestCheck(isCalled); + } - TEST_METHOD(FunctorRef_noexcept_LambdaReturnValue) - { - int addResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x + y; }); - TestCheckEqual(8, addResult); + TEST_METHOD(FunctorRef_noexcept_MsoFunctor) + { + // It can be useful in case when we have an std::function available. + bool isCalled = false; + auto func = Mso::VoidFunctor([&isCalled]() noexcept { isCalled = true; }); + TestClass::Execute(func); + TestCheck(isCalled); + } - int multResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x * y; }); - TestCheckEqual(15, multResult); - } + TEST_METHOD(FunctorRef_noexcept_LambdaReturnValue) + { + int addResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x + y; }); + TestCheckEqual(8, addResult); - TEST_METHOD(FunctorRef_noexcept_LambdaPassParamByRef) - { - // Pass an Mso::TCntPtr as an const reference and see that it was never called AddRef() - MyParam param; - auto spParam = Mso::TCntPtr(¶m); - TestCheckEqual(1, param.AddRefCount); - param.Value = 10; + int multResult = TestClass::Aggregate(3, 5, [](int x, int y) noexcept { return x * y; }); + TestCheckEqual(15, multResult); + } - int result = TestClass::PassByRef(spParam, [](const Mso::TCntPtr& p) noexcept { return p->Value; }); - TestCheckEqual(10, result); - TestCheckEqual(1, param.AddRefCount); - } + TEST_METHOD(FunctorRef_noexcept_LambdaPassParamByRef) + { + // Pass an Mso::TCntPtr as an const reference and see that it was never called AddRef() + MyParam param; + auto spParam = Mso::TCntPtr(¶m); + TestCheckEqual(1, param.AddRefCount); + param.Value = 10; - TEST_METHOD(FunctorRef_noexcept_LambdaPassParamAsRValue) - { - // Pass an Mso::TCntPtr as an r-value and see that it was never called AddRef() - MyParam param; - auto spParam = Mso::TCntPtr(¶m); - TestCheckEqual(1, param.AddRefCount); + int result = TestClass::PassByRef(spParam, [](const Mso::TCntPtr& p) noexcept { return p->Value; }); + TestCheckEqual(10, result); + TestCheckEqual(1, param.AddRefCount); + } - auto spParam2 = TestClass::PassAsRValue(std::move(spParam), [](Mso::TCntPtr&& p) noexcept { return std::move(p); }); - TestCheckEqual(1, param.AddRefCount); - } + TEST_METHOD(FunctorRef_noexcept_LambdaPassParamAsRValue) + { + // Pass an Mso::TCntPtr as an r-value and see that it was never called AddRef() + MyParam param; + auto spParam = Mso::TCntPtr(¶m); + TestCheckEqual(1, param.AddRefCount); - TEST_METHOD(FunctorRefThrow_StdFunction) - { - // We use the std::function as an example of throwing function object. - bool isCalled = false; - TestClass::ExecuteThrow(std::function([&isCalled]() noexcept { isCalled = true; })); - TestCheck(isCalled); - } + auto spParam2 = + TestClass::PassAsRValue(std::move(spParam), [](Mso::TCntPtr&& p) noexcept { return std::move(p); }); + TestCheckEqual(1, param.AddRefCount); + } - TEST_METHOD(FunctorRefThrow_LambdaReturnValue) - { - int addResult = TestClass::AggregateThrow(3, 5, std::function([](int x, int y) noexcept { return x + y; })); - TestCheckEqual(8, addResult); + TEST_METHOD(FunctorRefThrow_StdFunction) + { + // We use the std::function as an example of throwing function object. + bool isCalled = false; + TestClass::ExecuteThrow(std::function([&isCalled]() noexcept { isCalled = true; })); + TestCheck(isCalled); + } - int multResult = TestClass::AggregateThrow(3, 5, std::function([](int x, int y) noexcept{ return x * y; })); - TestCheckEqual(15, multResult); - } + TEST_METHOD(FunctorRefThrow_LambdaReturnValue) + { + int addResult = + TestClass::AggregateThrow(3, 5, std::function([](int x, int y) noexcept { return x + y; })); + TestCheckEqual(8, addResult); - TEST_METHOD(FunctorRefThrow_LambdaPassParamByRef) - { - // Pass an Mso::TCntPtr as an const reference and see that it was never called AddRef() - MyParam param; - auto spParam = Mso::TCntPtr(¶m); - TestCheckEqual(1, param.AddRefCount); - param.Value = 10; + int multResult = + TestClass::AggregateThrow(3, 5, std::function([](int x, int y) noexcept { return x * y; })); + TestCheckEqual(15, multResult); + } - using Function = std::function&)>; - int result = TestClass::PassByRefThrow(spParam, Function([](const Mso::TCntPtr& p) noexcept { return p->Value; })); - TestCheckEqual(10, result); - TestCheckEqual(1, param.AddRefCount); - } + TEST_METHOD(FunctorRefThrow_LambdaPassParamByRef) + { + // Pass an Mso::TCntPtr as an const reference and see that it was never called AddRef() + MyParam param; + auto spParam = Mso::TCntPtr(¶m); + TestCheckEqual(1, param.AddRefCount); + param.Value = 10; - TEST_METHOD(FunctorRefThrow_LambdaPassParamAsRValue) - { - // Pass an Mso::TCntPtr as an r-value and see that it was never called AddRef() - MyParam param; - auto spParam = Mso::TCntPtr(¶m); - TestCheckEqual(1, param.AddRefCount); + using Function = std::function&)>; + int result = + TestClass::PassByRefThrow(spParam, Function([](const Mso::TCntPtr& p) noexcept { return p->Value; })); + TestCheckEqual(10, result); + TestCheckEqual(1, param.AddRefCount); + } - using Function = std::function(Mso::TCntPtr&&)>; - auto spParam2 = TestClass::PassAsRValueThrow(std::move(spParam), Function([](Mso::TCntPtr&& p) noexcept { return std::move(p); })); - TestCheckEqual(1, param.AddRefCount); - } + TEST_METHOD(FunctorRefThrow_LambdaPassParamAsRValue) + { + // Pass an Mso::TCntPtr as an r-value and see that it was never called AddRef() + MyParam param; + auto spParam = Mso::TCntPtr(¶m); + TestCheckEqual(1, param.AddRefCount); - TEST_METHOD(FunctorRef_MutableLambda) - { - std::unique_ptr isCalled { nullptr }; - auto mutableValue = std::make_unique(true); + using Function = std::function(Mso::TCntPtr &&)>; + auto spParam2 = TestClass::PassAsRValueThrow( + std::move(spParam), Function([](Mso::TCntPtr&& p) noexcept { return std::move(p); })); + TestCheckEqual(1, param.AddRefCount); + } - TestClass::Execute([&isCalled, mutableValue = std::move(mutableValue)]() mutable noexcept - { - isCalled = std::move(mutableValue); - }); + TEST_METHOD(FunctorRef_MutableLambda) + { + std::unique_ptr isCalled{nullptr}; + auto mutableValue = std::make_unique(true); - TestCheck(*isCalled); - } + TestClass::Execute( + [&isCalled, mutableValue = std::move(mutableValue)]() mutable noexcept { isCalled = std::move(mutableValue); }); - TEST_METHOD(FunctorRefThrow_MutableLambda) - { - std::unique_ptr isCalled { nullptr }; - auto mutableValue = std::make_unique(true); + TestCheck(*isCalled); + } - TestClass::ExecuteThrow([&isCalled, mutableValue = std::move(mutableValue)]() mutable noexcept - { - isCalled = std::move(mutableValue); - }); + TEST_METHOD(FunctorRefThrow_MutableLambda) + { + std::unique_ptr isCalled{nullptr}; + auto mutableValue = std::make_unique(true); - TestCheck(*isCalled); - } + TestClass::ExecuteThrow( + [&isCalled, mutableValue = std::move(mutableValue)]() mutable noexcept { isCalled = std::move(mutableValue); }); -OACR_WARNING_PUSH -OACR_WARNING_DISABLE(BY_VALUE_TEMPLATEFORMAL_WITH_DTOR, "We want to test that we can pass by value") + TestCheck(*isCalled); + } - TEST_METHOD(FunctorRef_LambdaPassParamByValue) - { - auto inValue = std::make_unique(5); - auto result = TestClass::PassByValue(std::move(inValue), [](std::unique_ptr p) noexcept - { - return p; - }); - TestCheckEqual(5, *result); - } + OACR_WARNING_PUSH + OACR_WARNING_DISABLE(BY_VALUE_TEMPLATEFORMAL_WITH_DTOR, "We want to test that we can pass by value") - TEST_METHOD(FunctorRefThrow_LambdaPassParamByValue) - { - auto inValue = std::make_unique(5); - auto result = TestClass::PassByValueThrow(std::move(inValue), [](std::unique_ptr p) noexcept - { - return p; - }); - TestCheckEqual(5, *result); - } + TEST_METHOD(FunctorRef_LambdaPassParamByValue) + { + auto inValue = std::make_unique(5); + auto result = TestClass::PassByValue(std::move(inValue), [](std::unique_ptr p) noexcept { return p; }); + TestCheckEqual(5, *result); + } -OACR_WARNING_POP + TEST_METHOD(FunctorRefThrow_LambdaPassParamByValue) + { + auto inValue = std::make_unique(5); + auto result = TestClass::PassByValueThrow(std::move(inValue), [](std::unique_ptr p) noexcept { return p; }); + TestCheckEqual(5, *result); + } + OACR_WARNING_POP }; diff --git a/libs/functional/tests/functorTest.cpp b/libs/functional/tests/functorTest.cpp index 7612aab..9053017 100644 --- a/libs/functional/tests/functorTest.cpp +++ b/libs/functional/tests/functorTest.cpp @@ -17,503 +17,447 @@ using namespace FunctorTestsCommon; // To test how we can pass Functor to a method. struct VoidFunctorExecutor { - static void Execute(Mso::VoidFunctor&& func) noexcept - { - auto funcField = std::move(func); // Simulate storing functor in a field before execution. - funcField(); - } + static void Execute(Mso::VoidFunctor&& func) noexcept + { + auto funcField = std::move(func); // Simulate storing functor in a field before execution. + funcField(); + } }; // To test how we can pass FunctorThrow to a method. struct VoidFunctorThrowExecutor { - static void Execute(Mso::VoidFunctorThrow&& func) - { - auto funcField = std::move(func); // Simulate storing functor in a field before execution. - funcField(); - } + static void Execute(Mso::VoidFunctorThrow&& func) + { + auto funcField = std::move(func); // Simulate storing functor in a field before execution. + funcField(); + } }; struct TestVoidFunctor : Mso::VoidFunctorImpl { - virtual void Invoke() noexcept override - { - ++m_callCount; - } + virtual void Invoke() noexcept override + { + ++m_callCount; + } - int32_t m_callCount{ 0 }; + int32_t m_callCount{0}; }; struct TestVoidFunctorThrow : Mso::VoidFunctorThrowImpl { - virtual void Invoke() override - { - ++m_callCount; - } + virtual void Invoke() override + { + ++m_callCount; + } - int32_t m_callCount { 0 }; + int32_t m_callCount{0}; }; // To test how we can pass std::function to a method. struct MyFunctorExecutor { - static void Execute(Mso::Functor&& func) noexcept - { - auto funcField = std::move(func); // Simulate storing functor in a field before execution. - StructParam param; - funcField(¶m); - } + static void Execute(Mso::Functor&& func) noexcept + { + auto funcField = std::move(func); // Simulate storing functor in a field before execution. + StructParam param; + funcField(¶m); + } }; // To test how we can pass std::function to a method. struct MyFunctorThrowExecutor { - static void Execute(Mso::FunctorThrow&& func) - { - auto funcField = std::move(func); // Simulate storing functor in a field before execution. - StructParam param; - funcField(¶m); - } + static void Execute(Mso::FunctorThrow&& func) + { + auto funcField = std::move(func); // Simulate storing functor in a field before execution. + StructParam param; + funcField(¶m); + } }; int g_freeFunctionState = 0; static void TestFreeFunction_Increment() noexcept { - g_freeFunctionState++; + g_freeFunctionState++; } static void TestFreeFunction_Decrement() noexcept { - g_freeFunctionState--; + g_freeFunctionState--; } static int TestFreeFunction_Add(int i) noexcept { - g_freeFunctionState += i; - return g_freeFunctionState; + g_freeFunctionState += i; + return g_freeFunctionState; } static int TestFreeFunction_Subtract(int i) noexcept { - g_freeFunctionState -= i; - return g_freeFunctionState; + g_freeFunctionState -= i; + return g_freeFunctionState; } static void TestFreeFunction_Throw(int i) { - if (i < 0) - throw std::runtime_error("test"); + if (i < 0) + throw std::runtime_error("test"); } -TestClassComponent(FunctorTest, Mso.Functor) -TEST_CLASS(FunctorTest) +TestClassComponent(FunctorTest, Mso.Functor) TEST_CLASS (FunctorTest) { - TEST_METHOD(Functor_ctor_Default) - { - Mso::Functor f1; - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(Functor_ctor_Default) + { + Mso::Functor f1; + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(Functor_ctor_nullptr) - { - Mso::Functor f1(nullptr); - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(Functor_ctor_nullptr) + { + Mso::Functor f1(nullptr); + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(Functor_ctor_Copy) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2(f1); - TestCheck(!f1.IsEmpty()); - TestCheck(f1 == f2); - } + TEST_METHOD(Functor_ctor_Copy) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2(f1); + TestCheck(!f1.IsEmpty()); + TestCheck(f1 == f2); + } - TEST_METHOD(Functor_ctor_Move) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2(f1); // copy of f1 - Mso::Functor f3(std::move(f1)); - TestCheck(f1.IsEmpty()); - TestCheck(!f3.IsEmpty()); - TestCheck(f3 == f2); - } + TEST_METHOD(Functor_ctor_Move) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2(f1); // copy of f1 + Mso::Functor f3(std::move(f1)); + TestCheck(f1.IsEmpty()); + TestCheck(!f3.IsEmpty()); + TestCheck(f3 == f2); + } - TEST_METHOD(Functor_ctor_DoNothingFunctor) - { - auto f1 = Mso::Functor::DoNothing(); - auto f2 = Mso::Functor::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == f2.Get()); - } + TEST_METHOD(Functor_ctor_DoNothingFunctor) + { + auto f1 = Mso::Functor::DoNothing(); + auto f2 = Mso::Functor::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == f2.Get()); + } - TEST_METHOD(VoidFunctor_ctor_DoNothingFunctor) - { - auto f1 = Mso::VoidFunctor::DoNothing(); - auto f2 = Mso::VoidFunctor::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == f2.Get()); - } + TEST_METHOD(VoidFunctor_ctor_DoNothingFunctor) + { + auto f1 = Mso::VoidFunctor::DoNothing(); + auto f2 = Mso::VoidFunctor::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == f2.Get()); + } - TEST_METHOD(Functor_ctor_IFunctor_Ptr) - { - auto functorImpl = Mso::Make(); - Mso::VoidFunctor f1(functorImpl.Get()); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_ctor_IFunctor_Ptr) + { + auto functorImpl = Mso::Make(); + Mso::VoidFunctor f1(functorImpl.Get()); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_TCntPtrCopy) - { - auto functorImpl = Mso::Make(); - Mso::VoidFunctor f1(functorImpl); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_ctor_IFunctor_TCntPtrCopy) + { + auto functorImpl = Mso::Make(); + Mso::VoidFunctor f1(functorImpl); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_ConstTCntPtrCopy) - { - const auto functorImpl = Mso::Make(); - Mso::VoidFunctor f1(functorImpl); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_ctor_IFunctor_ConstTCntPtrCopy) + { + const auto functorImpl = Mso::Make(); + Mso::VoidFunctor f1(functorImpl); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_TCntPtrMove) - { - auto functorImpl = Mso::Make(); - Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count - Mso::VoidFunctor f1(std::move(functorImplCopy)); - TestCheck(!f1.IsEmpty()); - TestCheck(functorImplCopy.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_ctor_IFunctor_TCntPtrMove) + { + auto functorImpl = Mso::Make(); + Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count + Mso::VoidFunctor f1(std::move(functorImplCopy)); + TestCheck(!f1.IsEmpty()); + TestCheck(functorImplCopy.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_Ptr_PassToMethod) - { - auto functorImpl = Mso::Make(); - VoidFunctorExecutor::Execute(functorImpl.Get()); + TEST_METHOD(Functor_ctor_IFunctor_Ptr_PassToMethod) + { + auto functorImpl = Mso::Make(); + VoidFunctorExecutor::Execute(functorImpl.Get()); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_TCntPtrCopy_PassToMethod) - { - auto functorImpl = Mso::Make(); - VoidFunctorExecutor::Execute(functorImpl); + TEST_METHOD(Functor_ctor_IFunctor_TCntPtrCopy_PassToMethod) + { + auto functorImpl = Mso::Make(); + VoidFunctorExecutor::Execute(functorImpl); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_ConstTCntPtrCopy_PassToMethod) - { - const auto functorImpl = Mso::Make(); - VoidFunctorExecutor::Execute(functorImpl); + TEST_METHOD(Functor_ctor_IFunctor_ConstTCntPtrCopy_PassToMethod) + { + const auto functorImpl = Mso::Make(); + VoidFunctorExecutor::Execute(functorImpl); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_IFunctor_TCntPtrMove_PassToMethod) - { - auto functorImpl = Mso::Make(); - Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count - VoidFunctorExecutor::Execute(std::move(functorImplCopy)); + TEST_METHOD(Functor_ctor_IFunctor_TCntPtrMove_PassToMethod) + { + auto functorImpl = Mso::Make(); + Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count + VoidFunctorExecutor::Execute(std::move(functorImplCopy)); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_ctor_Lambda) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_ctor_Lambda) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_ctor_Lambda_copy) - { - auto lambda = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f1(lambda); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_ctor_Lambda_copy) + { + auto lambda = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f1(lambda); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_ctor_Lambda_move) - { - auto lambda = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f1(std::move(lambda)); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_ctor_Lambda_move) + { + auto lambda = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f1(std::move(lambda)); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_ctor_Lambda_CaptureCopyCount) - { - int addRefCalls = 0; - int releaseCalls = 0; - { - auto data = Mso::Make(addRefCalls, releaseCalls); - data->Value = 3; - Mso::Functor f1 = ([data](int x, int y) noexcept - { - return x + y + data->Value; - }); + TEST_METHOD(Functor_ctor_Lambda_CaptureCopyCount) + { + int addRefCalls = 0; + int releaseCalls = 0; + { + auto data = Mso::Make(addRefCalls, releaseCalls); + data->Value = 3; + Mso::Functor f1 = ([data](int x, int y) noexcept { return x + y + data->Value; }); - TestCheckEqual(13, f1(4, 6)); - } + TestCheckEqual(13, f1(4, 6)); + } - TestCheckEqual(1, addRefCalls); - TestCheckEqual(2, releaseCalls); - } + TestCheckEqual(1, addRefCalls); + TestCheckEqual(2, releaseCalls); + } - TEST_METHOD(Functor_ctor_Lambda_MoveCapture) - { - int addRefCalls = 0; - int releaseCalls = 0; - { - auto data = Mso::Make(addRefCalls, releaseCalls); - data->Value = 3; - Mso::Functor f1 = [movedData = std::move(data)](int x, int y) noexcept - { - return x + y + movedData->Value; - }; + TEST_METHOD(Functor_ctor_Lambda_MoveCapture) + { + int addRefCalls = 0; + int releaseCalls = 0; + { + auto data = Mso::Make(addRefCalls, releaseCalls); + data->Value = 3; + Mso::Functor f1 = [movedData = std::move(data)](int x, int y) noexcept { + return x + y + movedData->Value; + }; - TestCheckEqual(13, f1(4, 6)); - } + TestCheckEqual(13, f1(4, 6)); + } - TestCheckEqual(0, addRefCalls); - TestCheckEqual(1, releaseCalls); - } + TestCheckEqual(0, addRefCalls); + TestCheckEqual(1, releaseCalls); + } - TEST_METHOD(Functor_ctor_MutableLambda) - { - Mso::Functor increment([i = 0]() mutable noexcept -> int - { - return i++; - }); + TEST_METHOD(Functor_ctor_MutableLambda) + { + Mso::Functor increment([i = 0]() mutable noexcept -> int { return i++; }); - TestCheckEqual(0, increment()); - TestCheckEqual(1, increment()); - } + TestCheckEqual(0, increment()); + TestCheckEqual(1, increment()); + } - TEST_METHOD(Functor_ctor_MutableLambda_NoCapture) - { - static int i = 0; - i = 0; - Mso::Functor increment([]() mutable noexcept -> int - { - return i++; - }); + TEST_METHOD(Functor_ctor_MutableLambda_NoCapture) + { + static int i = 0; + i = 0; + Mso::Functor increment([]() mutable noexcept -> int { return i++; }); - TestCheckEqual(0, increment()); - TestCheckEqual(1, increment()); - } + TestCheckEqual(0, increment()); + TestCheckEqual(1, increment()); + } - TEST_METHOD(Functor_ctor_StaticMethod) - { - // noexcept is not part of function pointer until C++17 - Mso::Functor f1 { &StaticMethod::Add, Mso::TerminateOnException }; - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_ctor_StaticMethod) + { + // noexcept is not part of function pointer until C++17 + Mso::Functor f1{&StaticMethod::Add, Mso::TerminateOnException}; + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_ctor_StdFunctionCopy) - { - int callCount = 0; - int value = 0; - auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::Functor f1(func, Mso::TerminateOnException); - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(Functor_ctor_StdFunctionCopy) + { + int callCount = 0; + int value = 0; + auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::Functor f1(func, Mso::TerminateOnException); + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(Functor_ctor_ConstStdFunctionCopy) - { - int callCount = 0; - int value = 0; - const auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::Functor f1(func, Mso::TerminateOnException); - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(Functor_ctor_ConstStdFunctionCopy) + { + int callCount = 0; + int value = 0; + const auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::Functor f1(func, Mso::TerminateOnException); + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(Functor_ctor_StdFunctionMove) - { - int callCount = 0; - int value = 0; - auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::Functor f1(std::move(func), Mso::TerminateOnException); - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(Functor_ctor_StdFunctionMove) + { + int callCount = 0; + int value = 0; + auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::Functor f1(std::move(func), Mso::TerminateOnException); + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(Functor_ctor_StdFunctionCopy_PassToMethod) - { - int callCount = 0; - auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_ctor_StdFunctionCopy_PassToMethod) + { + int callCount = 0; + auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_ctor_ConstStdFunctionCopy_PassToMethod) - { - int callCount = 0; - const auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_ctor_ConstStdFunctionCopy_PassToMethod) + { + int callCount = 0; + const auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_ctor_StdFunctionMove_PassToMethod) - { - int callCount = 0; - auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorExecutor::Execute({ std::move(func), Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_ctor_StdFunctionMove_PassToMethod) + { + int callCount = 0; + auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorExecutor::Execute({std::move(func), Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_ctor_StdFunctionCopy_DifferentSignature_PassToMethod) - { - int callCount = 0; - auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_ctor_StdFunctionCopy_DifferentSignature_PassToMethod) + { + int callCount = 0; + auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_ctor_ConstStdFunctionCopy_DifferentSignature_PassToMethod) - { - int callCount = 0; - const auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_ctor_ConstStdFunctionCopy_DifferentSignature_PassToMethod) + { + int callCount = 0; + const auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_ctor_StdFunctionMove_DifferentSignature_PassToMethod) - { - int callCount = 0; - auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorExecutor::Execute({ std::move(func), Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_ctor_StdFunctionMove_DifferentSignature_PassToMethod) + { + int callCount = 0; + auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorExecutor::Execute({std::move(func), Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_Assign_nullptr) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - f1 = nullptr; - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(Functor_Assign_nullptr) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + f1 = nullptr; + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(Functor_Assign_Copy) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - TestCheck(f1 != f2); - Mso::Functor f3(f1); // copy of f1 - f1 = f2; - TestCheck(!f2.IsEmpty()); - TestCheck(f1 == f2); - TestCheck(f1 != f3); - } + TEST_METHOD(Functor_Assign_Copy) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + TestCheck(f1 != f2); + Mso::Functor f3(f1); // copy of f1 + f1 = f2; + TestCheck(!f2.IsEmpty()); + TestCheck(f1 == f2); + TestCheck(f1 != f3); + } - TEST_METHOD(Functor_Assign_Move) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4(f2); // copy of f2 - f1 = std::move(f2); - TestCheck(!f1.IsEmpty()); - TestCheck(f2.IsEmpty()); - TestCheck(f1 != f3); - TestCheck(f1 == f4); - } + TEST_METHOD(Functor_Assign_Move) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4(f2); // copy of f2 + f1 = std::move(f2); + TestCheck(!f1.IsEmpty()); + TestCheck(f2.IsEmpty()); + TestCheck(f1 != f3); + TestCheck(f1 == f4); + } - TESTMETHOD_REQUIRES_SEH(Functor_operator_call_Empty) - { - Mso::Functor f1; - TestCheckCrash(f1(1, 2)); - } + TESTMETHOD_REQUIRES_SEH(Functor_operator_call_Empty) + { + Mso::Functor f1; + TestCheckCrash(f1(1, 2)); + } - TEST_METHOD(Functor_operator_call_NonEmpty) - { - Mso::Functor f1 = ([](int x, int y) noexcept - { - return x + y; - }); - TestCheckEqual(10, f1(4, 6)); - } + TEST_METHOD(Functor_operator_call_NonEmpty) + { + Mso::Functor f1 = ([](int x, int y) noexcept { return x + y; }); + TestCheckEqual(10, f1(4, 6)); + } #if 0 TESTMETHOD_REQUIRES_SEH(Functor_operator_call_Throws) { Mso::Functor f1 = ([](int) noexcept -> int { OACR_NOEXCEPT_MAYTERMINATE; - #pragma warning(suppress:4297) // Suppress warning about throwing in noexcept function. +#pragma warning(suppress : 4297) // Suppress warning about throwing in noexcept function. throw std::runtime_error("Test error"); }); TestCheckTerminate(f1(5)); @@ -531,550 +475,459 @@ TEST_CLASS(FunctorTest) TestCheckEqual(1, callCount); } #endif - TEST_METHOD(Functor_operator_call_Void) - { - int result = 0; - Mso::Functor f1 = [&result](int x, int y) noexcept - { - result = x + y; - }; - TestCheck(!f1.IsEmpty()); - f1(4, 6); - TestCheckEqual(10, result); - } + TEST_METHOD(Functor_operator_call_Void) + { + int result = 0; + Mso::Functor f1 = [&result](int x, int y) noexcept { result = x + y; }; + TestCheck(!f1.IsEmpty()); + f1(4, 6); + TestCheckEqual(10, result); + } - TEST_METHOD(Functor_operator_call_WithCapture) - { - int bias = 5; - auto add = Mso::Functor([bias](int x, int y) noexcept - { - return x + y + bias; - }); - TestCheckEqual(15, add(4, 6)); - } + TEST_METHOD(Functor_operator_call_WithCapture) + { + int bias = 5; + auto add = Mso::Functor([bias](int x, int y) noexcept { return x + y + bias; }); + TestCheckEqual(15, add(4, 6)); + } - TEST_METHOD(Functor_IsEmpty) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2; - TestCheck(!f1.IsEmpty()); - TestCheck(f2.IsEmpty()); - } + TEST_METHOD(Functor_IsEmpty) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2; + TestCheck(!f1.IsEmpty()); + TestCheck(f2.IsEmpty()); + } - TEST_METHOD(Functor_operator_bool) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2; - TestCheck(f1); - TestCheck(!f2); - } + TEST_METHOD(Functor_operator_bool) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2; + TestCheck(f1); + TestCheck(!f2); + } - TEST_METHOD(Functor_Swap) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4(f2); // copy of f2 - f1.Swap(f2); - TestCheck(f1 == f4); - TestCheck(f2 == f3); - } + TEST_METHOD(Functor_Swap) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4(f2); // copy of f2 + f1.Swap(f2); + TestCheck(f1 == f4); + TestCheck(f2 == f3); + } - TEST_METHOD(Functor_std_swap) - { - using std::swap; // The typical pattern how to call the swap method. - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4(f2); // copy of f2 - swap(f1, f2); // Never use the std prefix for swap: the swap can be overridden in the namespace of T. - TestCheck(f1 == f4); - TestCheck(f2 == f3); - } + TEST_METHOD(Functor_std_swap) + { + using std::swap; // The typical pattern how to call the swap method. + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4(f2); // copy of f2 + swap(f1, f2); // Never use the std prefix for swap: the swap can be overridden in the namespace of T. + TestCheck(f1 == f4); + TestCheck(f2 == f3); + } - TEST_METHOD(Functor_Get) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2; - TestCheck(f1.Get() != nullptr); - TestCheck(f2.Get() == nullptr); - } + TEST_METHOD(Functor_Get) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2; + TestCheck(f1.Get() != nullptr); + TestCheck(f2.Get() == nullptr); + } - TEST_METHOD(Functor_Detach) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; + TEST_METHOD(Functor_Detach) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; - Mso::TCntPtr> impl(f1.Detach(), /*shouldAddRef*/false); - TestCheck(f1.IsEmpty()); - TestCheck(!impl.IsEmpty()); - } + Mso::TCntPtr> impl(f1.Detach(), /*shouldAddRef*/ false); + TestCheck(f1.IsEmpty()); + TestCheck(!impl.IsEmpty()); + } - TEST_METHOD(Functor_operator_Equal) - { - using std::swap; // The typical pattern how to call the swap method. - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4; - TestCheck(f1 == f3); - TestCheck(f3 == f1); - TestCheck(f1 != f2); - TestCheck(f2 != f1); - TestCheck(f4 != f1); - TestCheck(f1 != f4); - TestCheck(f4 == nullptr); - TestCheck(nullptr == f4); - TestCheck(f1 != nullptr); - TestCheck(nullptr != f1); - } + TEST_METHOD(Functor_operator_Equal) + { + using std::swap; // The typical pattern how to call the swap method. + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4; + TestCheck(f1 == f3); + TestCheck(f3 == f1); + TestCheck(f1 != f2); + TestCheck(f2 != f1); + TestCheck(f4 != f1); + TestCheck(f1 != f4); + TestCheck(f4 == nullptr); + TestCheck(nullptr == f4); + TestCheck(f1 != nullptr); + TestCheck(nullptr != f1); + } - TEST_METHOD(Functor_DoNothing) - { - Mso::Functor f1 = Mso::Functor::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(0, f1(1)); + TEST_METHOD(Functor_DoNothing) + { + Mso::Functor f1 = Mso::Functor::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(0, f1(1)); - Mso::Functor f2 = Mso::Functor::DoNothing(); - TestCheck(!f2.IsEmpty()); - TestCheckEqual(0.0, f2(3.14)); + Mso::Functor f2 = Mso::Functor::DoNothing(); + TestCheck(!f2.IsEmpty()); + TestCheckEqual(0.0, f2(3.14)); - Mso::Functor f3 = Mso::Functor::DoNothing(); - TestCheck(!f3.IsEmpty()); - TestCheckEqual(0, f3(100, 200)); + Mso::Functor f3 = Mso::Functor::DoNothing(); + TestCheck(!f3.IsEmpty()); + TestCheckEqual(0, f3(100, 200)); - Mso::Functor f4 = Mso::Functor::DoNothing(); - TestCheck(!f4.IsEmpty()); - TestCheckEqual(nullptr, f4(1000, 2000)); - } + Mso::Functor f4 = Mso::Functor::DoNothing(); + TestCheck(!f4.IsEmpty()); + TestCheckEqual(nullptr, f4(1000, 2000)); + } - TEST_METHOD(Functor_GenericLambda) - { - auto adder = [](const auto& a, const auto& b) noexcept { return a + b; }; + TEST_METHOD(Functor_GenericLambda) + { + auto adder = [](const auto& a, const auto& b) noexcept { return a + b; }; - Mso::Functor fnInt = adder; - Mso::Functor fnDouble = adder; - Mso::Functor fnString = adder; - } + Mso::Functor fnInt = adder; + Mso::Functor fnDouble = adder; + Mso::Functor fnString = adder; + } - TEST_METHOD(FunctorThrow_ctor_Default) - { - Mso::FunctorThrow f1; - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(FunctorThrow_ctor_Default) + { + Mso::FunctorThrow f1; + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(FunctorThrow_ctor_nullptr) - { - Mso::FunctorThrow f1(nullptr); - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(FunctorThrow_ctor_nullptr) + { + Mso::FunctorThrow f1(nullptr); + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(FunctorThrow_ctor_Copy) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2(f1); - TestCheck(!f1.IsEmpty()); - TestCheck(f1 == f2); - } + TEST_METHOD(FunctorThrow_ctor_Copy) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2(f1); + TestCheck(!f1.IsEmpty()); + TestCheck(f1 == f2); + } - TEST_METHOD(FunctorThrow_ctor_Move) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2(f1); // copy of f1 - Mso::FunctorThrow f3(std::move(f1)); - TestCheck(f1.IsEmpty()); - TestCheck(!f3.IsEmpty()); - TestCheck(f3 == f2); - } + TEST_METHOD(FunctorThrow_ctor_Move) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2(f1); // copy of f1 + Mso::FunctorThrow f3(std::move(f1)); + TestCheck(f1.IsEmpty()); + TestCheck(!f3.IsEmpty()); + TestCheck(f3 == f2); + } - TEST_METHOD(FunctorThrow_ctor_DoNothingFunctorThrow) - { - auto f1 = Mso::FunctorThrow::DoNothing(); - auto f2 = Mso::FunctorThrow::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == f2.Get()); - } + TEST_METHOD(FunctorThrow_ctor_DoNothingFunctorThrow) + { + auto f1 = Mso::FunctorThrow::DoNothing(); + auto f2 = Mso::FunctorThrow::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == f2.Get()); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_Ptr) - { - auto functorImpl = Mso::Make(); - Mso::VoidFunctorThrow f1(functorImpl.Get()); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_Ptr) + { + auto functorImpl = Mso::Make(); + Mso::VoidFunctorThrow f1(functorImpl.Get()); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrCopy) - { - auto functorImpl = Mso::Make(); - Mso::VoidFunctorThrow f1(functorImpl); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrCopy) + { + auto functorImpl = Mso::Make(); + Mso::VoidFunctorThrow f1(functorImpl); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_ConstTCntPtrCopy) - { - const auto functorImpl = Mso::Make(); - Mso::VoidFunctorThrow f1(functorImpl); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_ConstTCntPtrCopy) + { + const auto functorImpl = Mso::Make(); + Mso::VoidFunctorThrow f1(functorImpl); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrMove) - { - auto functorImpl = Mso::Make(); - Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count - Mso::VoidFunctorThrow f1(std::move(functorImplCopy)); - TestCheck(!f1.IsEmpty()); - TestCheck(functorImplCopy.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrMove) + { + auto functorImpl = Mso::Make(); + Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count + Mso::VoidFunctorThrow f1(std::move(functorImplCopy)); + TestCheck(!f1.IsEmpty()); + TestCheck(functorImplCopy.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_Ptr_PassToMethod) - { - auto functorImpl = Mso::Make(); - VoidFunctorThrowExecutor::Execute(functorImpl.Get()); + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_Ptr_PassToMethod) + { + auto functorImpl = Mso::Make(); + VoidFunctorThrowExecutor::Execute(functorImpl.Get()); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrCopy_PassToMethod) - { - auto functorImpl = Mso::Make(); - VoidFunctorThrowExecutor::Execute(functorImpl); + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrCopy_PassToMethod) + { + auto functorImpl = Mso::Make(); + VoidFunctorThrowExecutor::Execute(functorImpl); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_ConstTCntPtrCopy_PassToMethod) - { - const auto functorImpl = Mso::Make(); - VoidFunctorThrowExecutor::Execute(functorImpl); + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_ConstTCntPtrCopy_PassToMethod) + { + const auto functorImpl = Mso::Make(); + VoidFunctorThrowExecutor::Execute(functorImpl); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrMove_PassToMethod) - { - auto functorImpl = Mso::Make(); - Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count - VoidFunctorThrowExecutor::Execute(std::move(functorImplCopy)); + TEST_METHOD(FunctorThrow_ctor_IFunctorThrow_TCntPtrMove_PassToMethod) + { + auto functorImpl = Mso::Make(); + Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count + VoidFunctorThrowExecutor::Execute(std::move(functorImplCopy)); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(FunctorThrow_ctor_Lambda) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(FunctorThrow_ctor_Lambda) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(FunctorThrow_ctor_Lambda_copy) - { - auto lambda = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f1(lambda); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(FunctorThrow_ctor_Lambda_copy) + { + auto lambda = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f1(lambda); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(FunctorThrow_ctor_Lambda_move) - { - auto lambda = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f1(std::move(lambda)); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(FunctorThrow_ctor_Lambda_move) + { + auto lambda = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f1(std::move(lambda)); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(FunctorThrow_ctor_Lambda_CaptureCopyCount) - { - int addRefCalls = 0; - int releaseCalls = 0; - { - auto data = Mso::Make(addRefCalls, releaseCalls); - data->Value = 3; - Mso::FunctorThrow f1 = ([data](int x, int y) noexcept - { - return x + y + data->Value; - }); + TEST_METHOD(FunctorThrow_ctor_Lambda_CaptureCopyCount) + { + int addRefCalls = 0; + int releaseCalls = 0; + { + auto data = Mso::Make(addRefCalls, releaseCalls); + data->Value = 3; + Mso::FunctorThrow f1 = ([data](int x, int y) noexcept { return x + y + data->Value; }); - TestCheckEqual(13, f1(4, 6)); - } + TestCheckEqual(13, f1(4, 6)); + } - TestCheckEqual(1, addRefCalls); - TestCheckEqual(2, releaseCalls); - } + TestCheckEqual(1, addRefCalls); + TestCheckEqual(2, releaseCalls); + } - TEST_METHOD(FunctorThrow_ctor_Lambda_MoveCapture) - { - int addRefCalls = 0; - int releaseCalls = 0; - { - auto data = Mso::Make(addRefCalls, releaseCalls); - data->Value = 3; - Mso::FunctorThrow f1 = [movedData = std::move(data)](int x, int y) noexcept - { - return x + y + movedData->Value; - }; + TEST_METHOD(FunctorThrow_ctor_Lambda_MoveCapture) + { + int addRefCalls = 0; + int releaseCalls = 0; + { + auto data = Mso::Make(addRefCalls, releaseCalls); + data->Value = 3; + Mso::FunctorThrow f1 = [movedData = std::move(data)](int x, int y) noexcept { + return x + y + movedData->Value; + }; - TestCheckEqual(13, f1(4, 6)); - } + TestCheckEqual(13, f1(4, 6)); + } - TestCheckEqual(0, addRefCalls); - TestCheckEqual(1, releaseCalls); - } + TestCheckEqual(0, addRefCalls); + TestCheckEqual(1, releaseCalls); + } - TEST_METHOD(FunctorThrow_ctor_MutableLambda) - { - Mso::FunctorThrow increment([i = 0]() mutable noexcept -> int - { - return i++; - }); + TEST_METHOD(FunctorThrow_ctor_MutableLambda) + { + Mso::FunctorThrow increment([i = 0]() mutable noexcept -> int { return i++; }); - TestCheckEqual(0, increment()); - TestCheckEqual(1, increment()); - } + TestCheckEqual(0, increment()); + TestCheckEqual(1, increment()); + } - TEST_METHOD(FunctorThrow_ctor_MutableLambda_NoCapture) - { - static int i = 0; - i = 0; - Mso::FunctorThrow increment([]() mutable noexcept -> int - { - return i++; - }); + TEST_METHOD(FunctorThrow_ctor_MutableLambda_NoCapture) + { + static int i = 0; + i = 0; + Mso::FunctorThrow increment([]() mutable noexcept -> int { return i++; }); - TestCheckEqual(0, increment()); - TestCheckEqual(1, increment()); - } + TestCheckEqual(0, increment()); + TestCheckEqual(1, increment()); + } - TEST_METHOD(FunctorThrow_ctor_StaticMethod) - { - Mso::FunctorThrow f1 { &StaticMethod::Add }; - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(FunctorThrow_ctor_StaticMethod) + { + Mso::FunctorThrow f1{&StaticMethod::Add}; + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(FunctorThrow_ctor_StdFunctionCopy) - { - int callCount = 0; - int value = 0; - auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::FunctorThrow f1(func); - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(FunctorThrow_ctor_StdFunctionCopy) + { + int callCount = 0; + int value = 0; + auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::FunctorThrow f1(func); + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(FunctorThrow_ctor_ConstStdFunctionCopy) - { - int callCount = 0; - int value = 0; - const auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::FunctorThrow f1(func); - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(FunctorThrow_ctor_ConstStdFunctionCopy) + { + int callCount = 0; + int value = 0; + const auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::FunctorThrow f1(func); + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(FunctorThrow_ctor_StdFunctionMove) - { - int callCount = 0; - int value = 0; - auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::FunctorThrow f1(std::move(func)); - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(FunctorThrow_ctor_StdFunctionMove) + { + int callCount = 0; + int value = 0; + auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::FunctorThrow f1(std::move(func)); + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(FunctorThrow_ctor_StdFunctionCopy_PassToMethod) - { - int callCount = 0; - auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorThrowExecutor::Execute(func); - TestCheckEqual(1, callCount); - } + TEST_METHOD(FunctorThrow_ctor_StdFunctionCopy_PassToMethod) + { + int callCount = 0; + auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorThrowExecutor::Execute(func); + TestCheckEqual(1, callCount); + } - TEST_METHOD(FunctorThrow_ctor_ConstStdFunctionCopy_PassToMethod) - { - int callCount = 0; - const auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorThrowExecutor::Execute(func); - TestCheckEqual(1, callCount); - } + TEST_METHOD(FunctorThrow_ctor_ConstStdFunctionCopy_PassToMethod) + { + int callCount = 0; + const auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorThrowExecutor::Execute(func); + TestCheckEqual(1, callCount); + } - TEST_METHOD(FunctorThrow_ctor_StdFunctionMove_PassToMethod) - { - int callCount = 0; - auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorThrowExecutor::Execute(std::move(func)); - TestCheckEqual(1, callCount); - } + TEST_METHOD(FunctorThrow_ctor_StdFunctionMove_PassToMethod) + { + int callCount = 0; + auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorThrowExecutor::Execute(std::move(func)); + TestCheckEqual(1, callCount); + } - TEST_METHOD(FunctorThrow_ctor_StdFunctionCopy_DifferentSignature_PassToMethod) - { - int callCount = 0; - auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorThrowExecutor::Execute(func); - TestCheckEqual(1, callCount); - } + TEST_METHOD(FunctorThrow_ctor_StdFunctionCopy_DifferentSignature_PassToMethod) + { + int callCount = 0; + auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorThrowExecutor::Execute(func); + TestCheckEqual(1, callCount); + } - TEST_METHOD(FunctorThrow_ctor_ConstStdFunctionCopy_DifferentSignature_PassToMethod) - { - int callCount = 0; - const auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorThrowExecutor::Execute(func); - TestCheckEqual(1, callCount); - } + TEST_METHOD(FunctorThrow_ctor_ConstStdFunctionCopy_DifferentSignature_PassToMethod) + { + int callCount = 0; + const auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorThrowExecutor::Execute(func); + TestCheckEqual(1, callCount); + } - TEST_METHOD(FunctorThrow_ctor_StdFunctionMove_DifferentSignature_PassToMethod) - { - int callCount = 0; - auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorThrowExecutor::Execute(std::move(func)); - TestCheckEqual(1, callCount); - } + TEST_METHOD(FunctorThrow_ctor_StdFunctionMove_DifferentSignature_PassToMethod) + { + int callCount = 0; + auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorThrowExecutor::Execute(std::move(func)); + TestCheckEqual(1, callCount); + } - TEST_METHOD(FunctorThrow_Assign_nullptr) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - f1 = nullptr; - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(FunctorThrow_Assign_nullptr) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + f1 = nullptr; + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(FunctorThrow_Assign_Copy) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2 = [](int x, int y) noexcept - { - return x - y; - }; - TestCheck(f1 != f2); - Mso::FunctorThrow f3(f1); // copy of f1 - f1 = f2; - TestCheck(!f2.IsEmpty()); - TestCheck(f1 == f2); - TestCheck(f1 != f3); - } + TEST_METHOD(FunctorThrow_Assign_Copy) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2 = [](int x, int y) noexcept { return x - y; }; + TestCheck(f1 != f2); + Mso::FunctorThrow f3(f1); // copy of f1 + f1 = f2; + TestCheck(!f2.IsEmpty()); + TestCheck(f1 == f2); + TestCheck(f1 != f3); + } - TEST_METHOD(FunctorThrow_Assign_Move) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::FunctorThrow f3(f1); // copy of f1 - Mso::FunctorThrow f4(f2); // copy of f2 - f1 = std::move(f2); - TestCheck(!f1.IsEmpty()); - TestCheck(f2.IsEmpty()); - TestCheck(f1 != f3); - TestCheck(f1 == f4); - } + TEST_METHOD(FunctorThrow_Assign_Move) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2 = [](int x, int y) noexcept { return x - y; }; + Mso::FunctorThrow f3(f1); // copy of f1 + Mso::FunctorThrow f4(f2); // copy of f2 + f1 = std::move(f2); + TestCheck(!f1.IsEmpty()); + TestCheck(f2.IsEmpty()); + TestCheck(f1 != f3); + TestCheck(f1 == f4); + } - TESTMETHOD_REQUIRES_SEH(FunctorThrow_operator_call_Empty) - { - Mso::FunctorThrow f1; - TestCheckCrash(f1(1, 2)); - } + TESTMETHOD_REQUIRES_SEH(FunctorThrow_operator_call_Empty) + { + Mso::FunctorThrow f1; + TestCheckCrash(f1(1, 2)); + } - TEST_METHOD(FunctorThrow_operator_call_NonEmpty) - { - Mso::FunctorThrow f1 = ([](int x, int y) noexcept - { - return x + y; - }); - TestCheckEqual(10, f1(4, 6)); - } + TEST_METHOD(FunctorThrow_operator_call_NonEmpty) + { + Mso::FunctorThrow f1 = ([](int x, int y) noexcept { return x + y; }); + TestCheckEqual(10, f1(4, 6)); + } #if 0 TEST_METHOD(FunctorThrow_operator_call_Throws) { @@ -1097,293 +950,264 @@ TEST_CLASS(FunctorTest) TestCheckEqual(1, callCount); } #endif - TEST_METHOD(FunctorThrow_operator_call_Void) - { - int result = 0; - Mso::FunctorThrow f1 = [&result](int x, int y) noexcept - { - result = x + y; - }; - TestCheck(!f1.IsEmpty()); - f1(4, 6); - TestCheckEqual(10, result); - } + TEST_METHOD(FunctorThrow_operator_call_Void) + { + int result = 0; + Mso::FunctorThrow f1 = [&result](int x, int y) noexcept { result = x + y; }; + TestCheck(!f1.IsEmpty()); + f1(4, 6); + TestCheckEqual(10, result); + } - TEST_METHOD(FunctorThrow_operator_call_WithCapture) - { - int bias = 5; - auto add = Mso::FunctorThrow([bias](int x, int y) noexcept - { - return x + y + bias; - }); - TestCheckEqual(15, add(4, 6)); - } + TEST_METHOD(FunctorThrow_operator_call_WithCapture) + { + int bias = 5; + auto add = Mso::FunctorThrow([bias](int x, int y) noexcept { return x + y + bias; }); + TestCheckEqual(15, add(4, 6)); + } - TEST_METHOD(FunctorThrow_IsEmpty) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2; - TestCheck(!f1.IsEmpty()); - TestCheck(f2.IsEmpty()); - } + TEST_METHOD(FunctorThrow_IsEmpty) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2; + TestCheck(!f1.IsEmpty()); + TestCheck(f2.IsEmpty()); + } - TEST_METHOD(FunctorThrow_operator_bool) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2; - TestCheck(f1); - TestCheck(!f2); - } + TEST_METHOD(FunctorThrow_operator_bool) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2; + TestCheck(f1); + TestCheck(!f2); + } - TEST_METHOD(FunctorThrow_Swap) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::FunctorThrow f3(f1); // copy of f1 - Mso::FunctorThrow f4(f2); // copy of f2 - f1.Swap(f2); - TestCheck(f1 == f4); - TestCheck(f2 == f3); - } + TEST_METHOD(FunctorThrow_Swap) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2 = [](int x, int y) noexcept { return x - y; }; + Mso::FunctorThrow f3(f1); // copy of f1 + Mso::FunctorThrow f4(f2); // copy of f2 + f1.Swap(f2); + TestCheck(f1 == f4); + TestCheck(f2 == f3); + } - TEST_METHOD(FunctorThrow_std_swap) - { - using std::swap; // The typical pattern how to call the swap method. - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::FunctorThrow f3(f1); // copy of f1 - Mso::FunctorThrow f4(f2); // copy of f2 - swap(f1, f2); // Never use the std prefix for swap: the swap can be overridden in the namespace of T. - TestCheck(f1 == f4); - TestCheck(f2 == f3); - } + TEST_METHOD(FunctorThrow_std_swap) + { + using std::swap; // The typical pattern how to call the swap method. + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2 = [](int x, int y) noexcept { return x - y; }; + Mso::FunctorThrow f3(f1); // copy of f1 + Mso::FunctorThrow f4(f2); // copy of f2 + swap(f1, f2); // Never use the std prefix for swap: the swap can be overridden in the namespace of T. + TestCheck(f1 == f4); + TestCheck(f2 == f3); + } - TEST_METHOD(FunctorThrow_Get) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2; - TestCheck(f1.Get() != nullptr); - TestCheck(f2.Get() == nullptr); - } + TEST_METHOD(FunctorThrow_Get) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2; + TestCheck(f1.Get() != nullptr); + TestCheck(f2.Get() == nullptr); + } - TEST_METHOD(FunctorThrow_Detach) - { - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; + TEST_METHOD(FunctorThrow_Detach) + { + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; - Mso::TCntPtr> impl(f1.Detach(), /*shouldAddRef*/false); - TestCheck(f1.IsEmpty()); - TestCheck(!impl.IsEmpty()); - } + Mso::TCntPtr> impl(f1.Detach(), /*shouldAddRef*/ false); + TestCheck(f1.IsEmpty()); + TestCheck(!impl.IsEmpty()); + } - TEST_METHOD(FunctorThrow_operator_Equal) - { - using std::swap; // The typical pattern how to call the swap method. - Mso::FunctorThrow f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::FunctorThrow f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::FunctorThrow f3(f1); // copy of f1 - Mso::FunctorThrow f4; - TestCheck(f1 == f3); - TestCheck(f3 == f1); - TestCheck(f1 != f2); - TestCheck(f2 != f1); - TestCheck(f4 != f1); - TestCheck(f1 != f4); - TestCheck(f4 == nullptr); - TestCheck(nullptr == f4); - TestCheck(f1 != nullptr); - TestCheck(nullptr != f1); - } + TEST_METHOD(FunctorThrow_operator_Equal) + { + using std::swap; // The typical pattern how to call the swap method. + Mso::FunctorThrow f1 = [](int x, int y) noexcept { return x + y; }; + Mso::FunctorThrow f2 = [](int x, int y) noexcept { return x - y; }; + Mso::FunctorThrow f3(f1); // copy of f1 + Mso::FunctorThrow f4; + TestCheck(f1 == f3); + TestCheck(f3 == f1); + TestCheck(f1 != f2); + TestCheck(f2 != f1); + TestCheck(f4 != f1); + TestCheck(f1 != f4); + TestCheck(f4 == nullptr); + TestCheck(nullptr == f4); + TestCheck(f1 != nullptr); + TestCheck(nullptr != f1); + } - TEST_METHOD(FunctorThrow_DoNothing) - { - Mso::FunctorThrow f1 = Mso::FunctorThrow::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(0, f1(1)); + TEST_METHOD(FunctorThrow_DoNothing) + { + Mso::FunctorThrow f1 = Mso::FunctorThrow::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(0, f1(1)); - Mso::FunctorThrow f2 = Mso::FunctorThrow::DoNothing(); - TestCheck(!f2.IsEmpty()); - TestCheckEqual(0.0, f2(3.14)); + Mso::FunctorThrow f2 = Mso::FunctorThrow::DoNothing(); + TestCheck(!f2.IsEmpty()); + TestCheckEqual(0.0, f2(3.14)); - Mso::FunctorThrow f3 = Mso::FunctorThrow::DoNothing(); - TestCheck(!f3.IsEmpty()); - TestCheckEqual(0, f3(100, 200)); + Mso::FunctorThrow f3 = Mso::FunctorThrow::DoNothing(); + TestCheck(!f3.IsEmpty()); + TestCheckEqual(0, f3(100, 200)); - Mso::FunctorThrow f4 = Mso::FunctorThrow::DoNothing(); - TestCheck(!f4.IsEmpty()); - TestCheckEqual(nullptr, f4(1000, 2000)); - } + Mso::FunctorThrow f4 = Mso::FunctorThrow::DoNothing(); + TestCheck(!f4.IsEmpty()); + TestCheckEqual(nullptr, f4(1000, 2000)); + } - // Make sure that lambda can be matched to a correct Mso::Functor instantiation - struct CheckFunctorOverload final - { - using FunctorAlias1 = Mso::Functor; - using FunctorAlias2 = Mso::Functor; + // Make sure that lambda can be matched to a correct Mso::Functor instantiation + struct CheckFunctorOverload final + { + using FunctorAlias1 = Mso::Functor; + using FunctorAlias2 = Mso::Functor; - static int DoCheckOverload(const FunctorAlias1&) noexcept { return 1; } - static int DoCheckOverload(const FunctorAlias2&) noexcept { return 2; } + static int DoCheckOverload(const FunctorAlias1&) noexcept + { + return 1; + } + static int DoCheckOverload(const FunctorAlias2&) noexcept + { + return 2; + } - static int CheckOverload() noexcept - { - return DoCheckOverload([&](auto&) noexcept {}) + DoCheckOverload([&](auto&, auto&) noexcept {}); - } - }; + static int CheckOverload() noexcept + { + return DoCheckOverload([&](auto&) noexcept {}) + DoCheckOverload([&](auto&, auto&) noexcept {}); + } + }; - // Make sure that lambda can be matched to a correct Mso::FunctorThrow instantiation - struct CheckFunctorThrowOverload final - { - using FunctorAlias1 = Mso::FunctorThrow; - using FunctorAlias2 = Mso::FunctorThrow; + // Make sure that lambda can be matched to a correct Mso::FunctorThrow instantiation + struct CheckFunctorThrowOverload final + { + using FunctorAlias1 = Mso::FunctorThrow; + using FunctorAlias2 = Mso::FunctorThrow; - static int DoCheckOverload(const FunctorAlias1&) noexcept { return 1; } - static int DoCheckOverload(const FunctorAlias2&) noexcept { return 2; } + static int DoCheckOverload(const FunctorAlias1&) noexcept + { + return 1; + } + static int DoCheckOverload(const FunctorAlias2&) noexcept + { + return 2; + } - static int CheckOverload() noexcept - { - return DoCheckOverload([&](auto&) noexcept {}) + DoCheckOverload([&](auto&, auto&) noexcept {}); - } - }; + static int CheckOverload() noexcept + { + return DoCheckOverload([&](auto&) noexcept {}) + DoCheckOverload([&](auto&, auto&) noexcept {}); + } + }; - TEST_METHOD(Functor_CheckOverload) - { - TestCheckEqual(3, CheckFunctorOverload::CheckOverload()); - } + TEST_METHOD(Functor_CheckOverload) + { + TestCheckEqual(3, CheckFunctorOverload::CheckOverload()); + } - TEST_METHOD(FunctorThrow_CheckOverload) - { - TestCheckEqual(3, CheckFunctorThrowOverload::CheckOverload()); - } + TEST_METHOD(FunctorThrow_CheckOverload) + { + TestCheckEqual(3, CheckFunctorThrowOverload::CheckOverload()); + } - TEST_METHOD(Functor_MoveOnlyLambda) - { - std::unique_ptr uniquePtr = std::make_unique(123450); - auto lambda = [capturedUniquePtr = std::move(uniquePtr)](int x) noexcept - { - return *capturedUniquePtr + x; - }; + TEST_METHOD(Functor_MoveOnlyLambda) + { + std::unique_ptr uniquePtr = std::make_unique(123450); + auto lambda = [capturedUniquePtr = std::move(uniquePtr)](int x) noexcept { return *capturedUniquePtr + x; }; - Mso::Functor f1 = std::move(lambda); + Mso::Functor f1 = std::move(lambda); - TestCheck(!static_cast(uniquePtr)); - TestCheckEqual(123456, f1(6)); - } + TestCheck(!static_cast(uniquePtr)); + TestCheckEqual(123456, f1(6)); + } - TEST_METHOD(Functor_LambdaMoveOnlyParam) - { - std::unique_ptr uniquePtr = std::make_unique(123450); + TEST_METHOD(Functor_LambdaMoveOnlyParam) + { + std::unique_ptr uniquePtr = std::make_unique(123450); - Mso::Functor&&)> f1 = [](std::unique_ptr&& uniquePtrParam) noexcept - { - std::unique_ptr movedPtr = std::move(uniquePtrParam); - return *movedPtr + 6; - }; + Mso::Functor &&)> f1 = [](std::unique_ptr&& uniquePtrParam) noexcept { + std::unique_ptr movedPtr = std::move(uniquePtrParam); + return *movedPtr + 6; + }; - TestCheckEqual(123456, f1(std::move(uniquePtr))); - TestCheck(!static_cast(uniquePtr)); - } + TestCheckEqual(123456, f1(std::move(uniquePtr))); + TestCheck(!static_cast(uniquePtr)); + } - TEST_METHOD(Functor_LambdaCovarianceAndContravariance) - { - Derived derivedInitial; - derivedInitial.i = 123456; + TEST_METHOD(Functor_LambdaCovarianceAndContravariance) + { + Derived derivedInitial; + derivedInitial.i = 123456; - // FunctorTestsCommon::DerivedFromBaseClass returns a Derived& and takes a BaseClass&. - // Covariance of the return type means our functor can have a more generic return type - // compared to the function itself. Contravariance of the parameters means that the - // functor can have more specific parameter types compared to the function itself. + // FunctorTestsCommon::DerivedFromBaseClass returns a Derived& and takes a BaseClass&. + // Covariance of the return type means our functor can have a more generic return type + // compared to the function itself. Contravariance of the parameters means that the + // functor can have more specific parameter types compared to the function itself. #ifdef JUST_FOR_ILLUSTATION__CPP_17 - // 'noexcept' isn't maintained in the function pointer type until C++17 - Mso::Functor f1 { &DerivedFromBaseClass }; + // 'noexcept' isn't maintained in the function pointer type until C++17 + Mso::Functor f1{&DerivedFromBaseClass}; #else - Mso::Functor f1(&DerivedFromBaseClass, Mso::TerminateOnException); + Mso::Functor f1(&DerivedFromBaseClass, Mso::TerminateOnException); #endif - BaseClass& baseClass = f1(derivedInitial); + BaseClass& baseClass = f1(derivedInitial); - TestCheck(static_cast(&derivedInitial) != &baseClass); // Make sure we got a different object back - TestCheckEqual(baseClass.GetInt(), 123456); - } + TestCheck(static_cast(&derivedInitial) != &baseClass); // Make sure we got a different object back + TestCheckEqual(baseClass.GetInt(), 123456); + } -OACR_WARNING_PUSH -OACR_WARNING_DISABLE(NOEXCEPT_FUNC_THROWS, "std::terminate behavior is okay for unit test") - TEST_METHOD(Functor_FunctorMakesCopyPassesRefToLambda) - { - std::string str = "Hello, world!"; - bool stringMatched = false; - bool gotCopy = false; + OACR_WARNING_PUSH + OACR_WARNING_DISABLE(NOEXCEPT_FUNC_THROWS, "std::terminate behavior is okay for unit test") + TEST_METHOD(Functor_FunctorMakesCopyPassesRefToLambda) + { + std::string str = "Hello, world!"; + bool stringMatched = false; + bool gotCopy = false; - Mso::Functor f1 = [&](const std::string& strParam) noexcept - { - stringMatched = (strParam == "Hello, world!"); - gotCopy = (static_cast(&str) != static_cast(&strParam)); - }; + Mso::Functor f1 = [&](const std::string& strParam) noexcept { + stringMatched = (strParam == "Hello, world!"); + gotCopy = (static_cast(&str) != static_cast(&strParam)); + }; - f1(str); - TestCheck(stringMatched); - TestCheck(gotCopy); - } -OACR_WARNING_POP + f1(str); + TestCheck(stringMatched); + TestCheck(gotCopy); + } + OACR_WARNING_POP - TEST_METHOD(Functor_FromFunctionPtr_Void) - { - g_freeFunctionState = 0; + TEST_METHOD(Functor_FromFunctionPtr_Void) + { + g_freeFunctionState = 0; - Mso::VoidFunctor func = Mso::VoidFunctor::FromFunctionPtr<&TestFreeFunction_Increment>(); - TestCheckEqual(g_freeFunctionState, 0); - func(); - TestCheckEqual(g_freeFunctionState, 1); - func(); - TestCheckEqual(g_freeFunctionState, 2); + Mso::VoidFunctor func = Mso::VoidFunctor::FromFunctionPtr<&TestFreeFunction_Increment>(); + TestCheckEqual(g_freeFunctionState, 0); + func(); + TestCheckEqual(g_freeFunctionState, 1); + func(); + TestCheckEqual(g_freeFunctionState, 2); - func = Mso::VoidFunctor::FromFunctionPtr<&TestFreeFunction_Decrement>(); - func(); - TestCheckEqual(g_freeFunctionState, 1); - func(); - TestCheckEqual(g_freeFunctionState, 0); - } + func = Mso::VoidFunctor::FromFunctionPtr<&TestFreeFunction_Decrement>(); + func(); + TestCheckEqual(g_freeFunctionState, 1); + func(); + TestCheckEqual(g_freeFunctionState, 0); + } - TEST_METHOD(Functor_FromFunctionPtr) - { - g_freeFunctionState = 0; + TEST_METHOD(Functor_FromFunctionPtr) + { + g_freeFunctionState = 0; - Mso::Functor func = Mso::Functor::FromFunctionPtr<&TestFreeFunction_Add>(); - TestCheckEqual(func(5), 5); - TestCheckEqual(func(3), 8); + Mso::Functor func = Mso::Functor::FromFunctionPtr<&TestFreeFunction_Add>(); + TestCheckEqual(func(5), 5); + TestCheckEqual(func(3), 8); - func = Mso::Functor::FromFunctionPtr<&TestFreeFunction_Subtract>(); - TestCheckEqual(func(2), 6); - TestCheckEqual(func(6), 0); - } + func = Mso::Functor::FromFunctionPtr<&TestFreeFunction_Subtract>(); + TestCheckEqual(func(2), 6); + TestCheckEqual(func(6), 0); + } #if 0 TEST_METHOD(FunctorThrow_FromFunctionPtr_ThrowingFunction) { @@ -1396,381 +1220,331 @@ OACR_WARNING_POP #endif }; -TestClassComponent(FunctorNoexceptTest, Mso.Functor.Noexcept) -TEST_CLASS(FunctorNoexceptTest) +TestClassComponent(FunctorNoexceptTest, Mso.Functor.Noexcept) TEST_CLASS (FunctorNoexceptTest) { - TEST_METHOD(Functor_noexcept_ctor_Default) - { - Mso::Functor f1; - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(Functor_noexcept_ctor_Default) + { + Mso::Functor f1; + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(Functor_noexcept_ctor_nullptr) - { - Mso::Functor f1(nullptr); - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(Functor_noexcept_ctor_nullptr) + { + Mso::Functor f1(nullptr); + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(Functor_noexcept_ctor_Copy) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2(f1); - TestCheck(!f1.IsEmpty()); - TestCheck(f1 == f2); - } + TEST_METHOD(Functor_noexcept_ctor_Copy) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2(f1); + TestCheck(!f1.IsEmpty()); + TestCheck(f1 == f2); + } - TEST_METHOD(Functor_noexcept_ctor_Move) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2(f1); // copy of f1 - Mso::Functor f3(std::move(f1)); - TestCheck(f1.IsEmpty()); - TestCheck(!f3.IsEmpty()); - TestCheck(f3 == f2); - } + TEST_METHOD(Functor_noexcept_ctor_Move) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2(f1); // copy of f1 + Mso::Functor f3(std::move(f1)); + TestCheck(f1.IsEmpty()); + TestCheck(!f3.IsEmpty()); + TestCheck(f3 == f2); + } - TEST_METHOD(Functor_noexcept_ctor_DoNothingFunctor) - { - auto f1 = Mso::Functor::DoNothing(); - auto f2 = Mso::Functor::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == f2.Get()); - } + TEST_METHOD(Functor_noexcept_ctor_DoNothingFunctor) + { + auto f1 = Mso::Functor::DoNothing(); + auto f2 = Mso::Functor::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == f2.Get()); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_Ptr) - { - auto functorImpl = Mso::Make(); - Mso::VoidFunctor f1(functorImpl.Get()); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_noexcept_ctor_IFunctor_Ptr) + { + auto functorImpl = Mso::Make(); + Mso::VoidFunctor f1(functorImpl.Get()); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrCopy) - { - auto functorImpl = Mso::Make(); - Mso::VoidFunctor f1(functorImpl); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrCopy) + { + auto functorImpl = Mso::Make(); + Mso::VoidFunctor f1(functorImpl); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_ConstTCntPtrCopy) - { - const auto functorImpl = Mso::Make(); - Mso::VoidFunctor f1(functorImpl); - TestCheck(!f1.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_noexcept_ctor_IFunctor_ConstTCntPtrCopy) + { + const auto functorImpl = Mso::Make(); + Mso::VoidFunctor f1(functorImpl); + TestCheck(!f1.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrMove) - { - auto functorImpl = Mso::Make(); - Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count - Mso::VoidFunctor f1(std::move(functorImplCopy)); - TestCheck(!f1.IsEmpty()); - TestCheck(functorImplCopy.IsEmpty()); - TestCheck(f1.Get() == functorImpl.Get()); - f1(); - TestCheckEqual(1, functorImpl->m_callCount); - } + TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrMove) + { + auto functorImpl = Mso::Make(); + Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count + Mso::VoidFunctor f1(std::move(functorImplCopy)); + TestCheck(!f1.IsEmpty()); + TestCheck(functorImplCopy.IsEmpty()); + TestCheck(f1.Get() == functorImpl.Get()); + f1(); + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_Ptr_PassToMethod) - { - auto functorImpl = Mso::Make(); - VoidFunctorExecutor::Execute(functorImpl.Get()); + TEST_METHOD(Functor_noexcept_ctor_IFunctor_Ptr_PassToMethod) + { + auto functorImpl = Mso::Make(); + VoidFunctorExecutor::Execute(functorImpl.Get()); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrCopy_PassToMethod) - { - auto functorImpl = Mso::Make(); - VoidFunctorExecutor::Execute(functorImpl); + TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrCopy_PassToMethod) + { + auto functorImpl = Mso::Make(); + VoidFunctorExecutor::Execute(functorImpl); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_ConstTCntPtrCopy_PassToMethod) - { - const auto functorImpl = Mso::Make(); - VoidFunctorExecutor::Execute(functorImpl); + TEST_METHOD(Functor_noexcept_ctor_IFunctor_ConstTCntPtrCopy_PassToMethod) + { + const auto functorImpl = Mso::Make(); + VoidFunctorExecutor::Execute(functorImpl); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrMove_PassToMethod) - { - auto functorImpl = Mso::Make(); - Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count - VoidFunctorExecutor::Execute(std::move(functorImplCopy)); + TEST_METHOD(Functor_noexcept_ctor_IFunctor_TCntPtrMove_PassToMethod) + { + auto functorImpl = Mso::Make(); + Mso::TCntPtr functorImplCopy = functorImpl; // keep original to check call count + VoidFunctorExecutor::Execute(std::move(functorImplCopy)); - TestCheckEqual(1, functorImpl->m_callCount); - } + TestCheckEqual(1, functorImpl->m_callCount); + } - TEST_METHOD(Functor_noexcept_ctor_Lambda) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_noexcept_ctor_Lambda) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_noexcept_ctor_Lambda_copy) - { - auto lambda = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f1(lambda); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_noexcept_ctor_Lambda_copy) + { + auto lambda = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f1(lambda); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_noexcept_ctor_Lambda_move) - { - auto lambda = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f1(std::move(lambda)); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_noexcept_ctor_Lambda_move) + { + auto lambda = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f1(std::move(lambda)); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_noexcept_ctor_Lambda_CaptureCopyCount) - { - int addRefCalls = 0; - int releaseCalls = 0; - { - auto data = Mso::Make(addRefCalls, releaseCalls); - data->Value = 3; - Mso::Functor f1 = ([data](int x, int y) noexcept - { - return x + y + data->Value; - }); + TEST_METHOD(Functor_noexcept_ctor_Lambda_CaptureCopyCount) + { + int addRefCalls = 0; + int releaseCalls = 0; + { + auto data = Mso::Make(addRefCalls, releaseCalls); + data->Value = 3; + Mso::Functor f1 = ([data](int x, int y) noexcept { return x + y + data->Value; }); - TestCheckEqual(13, f1(4, 6)); - } + TestCheckEqual(13, f1(4, 6)); + } - TestCheckEqual(1, addRefCalls); - TestCheckEqual(2, releaseCalls); - } + TestCheckEqual(1, addRefCalls); + TestCheckEqual(2, releaseCalls); + } - TEST_METHOD(Functor_noexcept_ctor_Lambda_MoveCapture) - { - int addRefCalls = 0; - int releaseCalls = 0; - { - auto data = Mso::Make(addRefCalls, releaseCalls); - data->Value = 3; - Mso::Functor f1 = [movedData = std::move(data)](int x, int y) noexcept - { - return x + y + movedData->Value; - }; + TEST_METHOD(Functor_noexcept_ctor_Lambda_MoveCapture) + { + int addRefCalls = 0; + int releaseCalls = 0; + { + auto data = Mso::Make(addRefCalls, releaseCalls); + data->Value = 3; + Mso::Functor f1 = [movedData = std::move(data)](int x, int y) noexcept { + return x + y + movedData->Value; + }; - TestCheckEqual(13, f1(4, 6)); - } + TestCheckEqual(13, f1(4, 6)); + } - TestCheckEqual(0, addRefCalls); - TestCheckEqual(1, releaseCalls); - } + TestCheckEqual(0, addRefCalls); + TestCheckEqual(1, releaseCalls); + } - TEST_METHOD(Functor_noexcept_ctor_StaticMethod) - { - Mso::Functor f1{ &StaticMethod::Add, Mso::TerminateOnException }; - TestCheck(!f1.IsEmpty()); - TestCheckEqual(5, f1(2, 3)); - } + TEST_METHOD(Functor_noexcept_ctor_StaticMethod) + { + Mso::Functor f1{&StaticMethod::Add, Mso::TerminateOnException}; + TestCheck(!f1.IsEmpty()); + TestCheckEqual(5, f1(2, 3)); + } - TEST_METHOD(Functor_noexcept_ctor_StdFunctionCopy) - { - int callCount = 0; - int value = 0; - auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::Functor f1 { func, Mso::TerminateOnException }; - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(Functor_noexcept_ctor_StdFunctionCopy) + { + int callCount = 0; + int value = 0; + auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::Functor f1{func, Mso::TerminateOnException}; + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(Functor_noexcept_ctor_ConstStdFunctionCopy) - { - int callCount = 0; - int value = 0; - const auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::Functor f1 { func, Mso::TerminateOnException }; - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(Functor_noexcept_ctor_ConstStdFunctionCopy) + { + int callCount = 0; + int value = 0; + const auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::Functor f1{func, Mso::TerminateOnException}; + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(Functor_noexcept_ctor_StdFunctionMove) - { - int callCount = 0; - int value = 0; - auto func = std::function([&callCount, &value](int v) noexcept - { - ++callCount; value = v; return v; - }); - Mso::Functor f1 { std::move(func), Mso::TerminateOnException }; - TestCheckEqual(5, f1(5)); - TestCheckEqual(1, callCount); - TestCheckEqual(5, value); - } + TEST_METHOD(Functor_noexcept_ctor_StdFunctionMove) + { + int callCount = 0; + int value = 0; + auto func = std::function([&callCount, &value](int v) noexcept { + ++callCount; + value = v; + return v; + }); + Mso::Functor f1{std::move(func), Mso::TerminateOnException}; + TestCheckEqual(5, f1(5)); + TestCheckEqual(1, callCount); + TestCheckEqual(5, value); + } - TEST_METHOD(Functor_noexcept_ctor_StdFunctionCopy_PassToMethod) - { - int callCount = 0; - auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_noexcept_ctor_StdFunctionCopy_PassToMethod) + { + int callCount = 0; + auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_noexcept_ctor_ConstStdFunctionCopy_PassToMethod) - { - int callCount = 0; - const auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_noexcept_ctor_ConstStdFunctionCopy_PassToMethod) + { + int callCount = 0; + const auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_noexcept_ctor_StdFunctionMove_PassToMethod) - { - int callCount = 0; - auto func = std::function([&callCount]() noexcept - { - ++callCount; - }); - VoidFunctorExecutor::Execute({ std::move(func), Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_noexcept_ctor_StdFunctionMove_PassToMethod) + { + int callCount = 0; + auto func = std::function([&callCount]() noexcept { ++callCount; }); + VoidFunctorExecutor::Execute({std::move(func), Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_noexcept_ctor_StdFunctionCopy_DifferentSignature_PassToMethod) - { - int callCount = 0; - auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_noexcept_ctor_StdFunctionCopy_DifferentSignature_PassToMethod) + { + int callCount = 0; + auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_noexcept_ctor_ConstStdFunctionCopy_DifferentSignature_PassToMethod) - { - int callCount = 0; - const auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorExecutor::Execute({ func, Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_noexcept_ctor_ConstStdFunctionCopy_DifferentSignature_PassToMethod) + { + int callCount = 0; + const auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorExecutor::Execute({func, Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_noexcept_ctor_StdFunctionMove_DifferentSignature_PassToMethod) - { - int callCount = 0; - auto func = std::function)>([&callCount](Mso::TCntPtr) noexcept - { - ++callCount; - }); - MyFunctorExecutor::Execute({ std::move(func), Mso::TerminateOnException }); - TestCheckEqual(1, callCount); - } + TEST_METHOD(Functor_noexcept_ctor_StdFunctionMove_DifferentSignature_PassToMethod) + { + int callCount = 0; + auto func = std::function)>( + [&callCount](Mso::TCntPtr) noexcept { ++callCount; }); + MyFunctorExecutor::Execute({std::move(func), Mso::TerminateOnException}); + TestCheckEqual(1, callCount); + } - TEST_METHOD(Functor_noexcept_Assign_nullptr) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - f1 = nullptr; - TestCheck(f1.IsEmpty()); - } + TEST_METHOD(Functor_noexcept_Assign_nullptr) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + f1 = nullptr; + TestCheck(f1.IsEmpty()); + } - TEST_METHOD(Functor_noexcept_Assign_Copy) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - TestCheck(f1 != f2); - Mso::Functor f3(f1); // copy of f1 - f1 = f2; - TestCheck(!f2.IsEmpty()); - TestCheck(f1 == f2); - TestCheck(f1 != f3); - } + TEST_METHOD(Functor_noexcept_Assign_Copy) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + TestCheck(f1 != f2); + Mso::Functor f3(f1); // copy of f1 + f1 = f2; + TestCheck(!f2.IsEmpty()); + TestCheck(f1 == f2); + TestCheck(f1 != f3); + } - TEST_METHOD(Functor_noexcept_Assign_Move) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4(f2); // copy of f2 - f1 = std::move(f2); - TestCheck(!f1.IsEmpty()); - TestCheck(f2.IsEmpty()); - TestCheck(f1 != f3); - TestCheck(f1 == f4); - } + TEST_METHOD(Functor_noexcept_Assign_Move) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4(f2); // copy of f2 + f1 = std::move(f2); + TestCheck(!f1.IsEmpty()); + TestCheck(f2.IsEmpty()); + TestCheck(f1 != f3); + TestCheck(f1 == f4); + } - TESTMETHOD_REQUIRES_SEH(Functor_operator_call_Empty) - { - Mso::Functor f1; - TestCheckCrash(f1(1, 2)); - } + TESTMETHOD_REQUIRES_SEH(Functor_operator_call_Empty) + { + Mso::Functor f1; + TestCheckCrash(f1(1, 2)); + } - TEST_METHOD(Functor_noexcept_operator_call_NonEmpty) - { - Mso::Functor f1 = ([](int x, int y) noexcept - { - return x + y; - }); - TestCheckEqual(10, f1(4, 6)); - } + TEST_METHOD(Functor_noexcept_operator_call_NonEmpty) + { + Mso::Functor f1 = ([](int x, int y) noexcept { return x + y; }); + TestCheckEqual(10, f1(4, 6)); + } #if 0 TESTMETHOD_REQUIRES_SEH(Functor_operator_call_Throws) { Mso::Functor f1 = ([](int) noexcept -> int { OACR_NOEXCEPT_MAYTERMINATE; - #pragma warning(suppress:4297) // Suppress warning about throwing in noexcept function. +#pragma warning(suppress : 4297) // Suppress warning about throwing in noexcept function. throw std::runtime_error("Test error"); }); TestCheckTerminate(f1(5)); @@ -1788,169 +1562,139 @@ TEST_CLASS(FunctorNoexceptTest) TestCheckEqual(1, callCount); } #endif - TEST_METHOD(Functor_noexcept_operator_call_Void) - { - int result = 0; - Mso::Functor f1 = [&result](int x, int y) noexcept - { - result = x + y; - }; - TestCheck(!f1.IsEmpty()); - f1(4, 6); - TestCheckEqual(10, result); - } + TEST_METHOD(Functor_noexcept_operator_call_Void) + { + int result = 0; + Mso::Functor f1 = [&result](int x, int y) noexcept { result = x + y; }; + TestCheck(!f1.IsEmpty()); + f1(4, 6); + TestCheckEqual(10, result); + } - TEST_METHOD(Functor_noexcept_operator_call_WithCapture) - { - int bias = 5; - auto add = Mso::Functor([bias](int x, int y) noexcept - { - return x + y + bias; - }); - TestCheckEqual(15, add(4, 6)); - } + TEST_METHOD(Functor_noexcept_operator_call_WithCapture) + { + int bias = 5; + auto add = Mso::Functor([bias](int x, int y) noexcept { return x + y + bias; }); + TestCheckEqual(15, add(4, 6)); + } - TEST_METHOD(Functor_noexcept_IsEmpty) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2; - TestCheck(!f1.IsEmpty()); - TestCheck(f2.IsEmpty()); - } + TEST_METHOD(Functor_noexcept_IsEmpty) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2; + TestCheck(!f1.IsEmpty()); + TestCheck(f2.IsEmpty()); + } - TEST_METHOD(Functor_noexcept_operator_bool) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2; - TestCheck(f1); - TestCheck(!f2); - } + TEST_METHOD(Functor_noexcept_operator_bool) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2; + TestCheck(f1); + TestCheck(!f2); + } - TEST_METHOD(Functor_noexcept_Swap) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4(f2); // copy of f2 - f1.Swap(f2); - TestCheck(f1 == f4); - TestCheck(f2 == f3); - } + TEST_METHOD(Functor_noexcept_Swap) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4(f2); // copy of f2 + f1.Swap(f2); + TestCheck(f1 == f4); + TestCheck(f2 == f3); + } - TEST_METHOD(Functor_noexcept_std_swap) - { - using std::swap; // The typical pattern how to call the swap method. - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4(f2); // copy of f2 - swap(f1, f2); // Never use the std prefix for swap: the swap can be overridden in the namespace of T. - TestCheck(f1 == f4); - TestCheck(f2 == f3); - } + TEST_METHOD(Functor_noexcept_std_swap) + { + using std::swap; // The typical pattern how to call the swap method. + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4(f2); // copy of f2 + swap(f1, f2); // Never use the std prefix for swap: the swap can be overridden in the namespace of T. + TestCheck(f1 == f4); + TestCheck(f2 == f3); + } - TEST_METHOD(Functor_noexcept_Get) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2; - TestCheck(f1.Get() != nullptr); - TestCheck(f2.Get() == nullptr); - } + TEST_METHOD(Functor_noexcept_Get) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2; + TestCheck(f1.Get() != nullptr); + TestCheck(f2.Get() == nullptr); + } - TEST_METHOD(Functor_noexcept_Detach) - { - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; + TEST_METHOD(Functor_noexcept_Detach) + { + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; - Mso::TCntPtr> impl(f1.Detach(), /*shouldAddRef*/false); - TestCheck(f1.IsEmpty()); - TestCheck(!impl.IsEmpty()); - } + Mso::TCntPtr> impl(f1.Detach(), /*shouldAddRef*/ false); + TestCheck(f1.IsEmpty()); + TestCheck(!impl.IsEmpty()); + } - TEST_METHOD(Functor_noexcept_operator_Equal) - { - using std::swap; // The typical pattern how to call the swap method. - Mso::Functor f1 = [](int x, int y) noexcept - { - return x + y; - }; - Mso::Functor f2 = [](int x, int y) noexcept - { - return x - y; - }; - Mso::Functor f3(f1); // copy of f1 - Mso::Functor f4; - TestCheck(f1 == f3); - TestCheck(f3 == f1); - TestCheck(f1 != f2); - TestCheck(f2 != f1); - TestCheck(f4 != f1); - TestCheck(f1 != f4); - TestCheck(f4 == nullptr); - TestCheck(nullptr == f4); - TestCheck(f1 != nullptr); - TestCheck(nullptr != f1); - } + TEST_METHOD(Functor_noexcept_operator_Equal) + { + using std::swap; // The typical pattern how to call the swap method. + Mso::Functor f1 = [](int x, int y) noexcept { return x + y; }; + Mso::Functor f2 = [](int x, int y) noexcept { return x - y; }; + Mso::Functor f3(f1); // copy of f1 + Mso::Functor f4; + TestCheck(f1 == f3); + TestCheck(f3 == f1); + TestCheck(f1 != f2); + TestCheck(f2 != f1); + TestCheck(f4 != f1); + TestCheck(f1 != f4); + TestCheck(f4 == nullptr); + TestCheck(nullptr == f4); + TestCheck(f1 != nullptr); + TestCheck(nullptr != f1); + } - TEST_METHOD(Functor_noexcept_DoNothing) - { - Mso::Functor f1 = Mso::Functor::DoNothing(); - TestCheck(!f1.IsEmpty()); - TestCheckEqual(0, f1(1)); + TEST_METHOD(Functor_noexcept_DoNothing) + { + Mso::Functor f1 = Mso::Functor::DoNothing(); + TestCheck(!f1.IsEmpty()); + TestCheckEqual(0, f1(1)); - Mso::Functor f2 = Mso::Functor::DoNothing(); - TestCheck(!f2.IsEmpty()); - TestCheckEqual(0.0, f2(3.14)); + Mso::Functor f2 = Mso::Functor::DoNothing(); + TestCheck(!f2.IsEmpty()); + TestCheckEqual(0.0, f2(3.14)); - Mso::Functor f3 = Mso::Functor::DoNothing(); - TestCheck(!f3.IsEmpty()); - TestCheckEqual(0, f3(100, 200)); + Mso::Functor f3 = Mso::Functor::DoNothing(); + TestCheck(!f3.IsEmpty()); + TestCheckEqual(0, f3(100, 200)); - Mso::Functor f4 = Mso::Functor::DoNothing(); - TestCheck(!f4.IsEmpty()); - TestCheckEqual(nullptr, f4(1000, 2000)); - } + Mso::Functor f4 = Mso::Functor::DoNothing(); + TestCheck(!f4.IsEmpty()); + TestCheckEqual(nullptr, f4(1000, 2000)); + } - // Make sure that lambda can be matched to a correct Mso::Functor instantiation - struct CheckFunctorOverload final - { - using FunctorAlias1 = Mso::Functor; - using FunctorAlias2 = Mso::Functor; + // Make sure that lambda can be matched to a correct Mso::Functor instantiation + struct CheckFunctorOverload final + { + using FunctorAlias1 = Mso::Functor; + using FunctorAlias2 = Mso::Functor; - static int DoCheckOverload(const FunctorAlias1&) noexcept { return 1; } - static int DoCheckOverload(const FunctorAlias2&) noexcept { return 2; } + static int DoCheckOverload(const FunctorAlias1&) noexcept + { + return 1; + } + static int DoCheckOverload(const FunctorAlias2&) noexcept + { + return 2; + } - static int CheckOverload() noexcept - { - return DoCheckOverload([&](auto&) noexcept {}) + DoCheckOverload([&](auto&, auto&) noexcept {}); - } - }; + static int CheckOverload() noexcept + { + return DoCheckOverload([&](auto&) noexcept {}) + DoCheckOverload([&](auto&, auto&) noexcept {}); + } + }; - TEST_METHOD(Functor_noexcept_CheckOverload) - { - TestCheckEqual(3, CheckFunctorOverload::CheckOverload()); - } + TEST_METHOD(Functor_noexcept_CheckOverload) + { + TestCheckEqual(3, CheckFunctorOverload::CheckOverload()); + } }; diff --git a/libs/functional/tests/functorTestsCommon.h b/libs/functional/tests/functorTestsCommon.h index 0d7507d..1c71de1 100644 --- a/libs/functional/tests/functorTestsCommon.h +++ b/libs/functional/tests/functorTestsCommon.h @@ -9,79 +9,87 @@ Common code for functor (Functor, SmallFunctor) unit tests. namespace FunctorTestsCommon { -class TestData - : public Mso::RefCountedObjectNoVTable +class TestData : public Mso::RefCountedObjectNoVTable { - using Super = Mso::RefCountedObjectNoVTable; + using Super = Mso::RefCountedObjectNoVTable; public: - TestData(int& addRefCalls, int& releaseCalls) noexcept - : m_addRefCalls(addRefCalls) - , m_releaseCalls(releaseCalls) - , Value(0) - { - } + TestData(int& addRefCalls, int& releaseCalls) noexcept + : m_addRefCalls(addRefCalls), m_releaseCalls(releaseCalls), Value(0) + { + } - void AddRef() const - { - ++m_addRefCalls; - Super::AddRef(); - } + void AddRef() const + { + ++m_addRefCalls; + Super::AddRef(); + } - void Release() const - { - ++m_releaseCalls; - Super::Release(); - } + void Release() const + { + ++m_releaseCalls; + Super::Release(); + } - int Value; + int Value; private: - int& m_addRefCalls; - int& m_releaseCalls; + int& m_addRefCalls; + int& m_releaseCalls; }; struct StaticMethod { - static int Add(int x, int y) noexcept - { - return x + y; - } + static int Add(int x, int y) noexcept + { + return x + y; + } -OACR_WARNING_PUSH -OACR_WARNING_DISABLE(FUNC_COULD_BE_NOEXCEPT, "Simple non-nonexcept function for use in unit tests") - static int AddThrow(int x, int y) - { - return x + y; - } -OACR_WARNING_POP + OACR_WARNING_PUSH + OACR_WARNING_DISABLE(FUNC_COULD_BE_NOEXCEPT, "Simple non-nonexcept function for use in unit tests") + static int AddThrow(int x, int y) + { + return x + y; + } + OACR_WARNING_POP }; struct StructParam { - void AddRef() const { UNREFERENCED_OACR(this); } - void Release() const { UNREFERENCED_OACR(this); } + void AddRef() const + { + UNREFERENCED_OACR(this); + } + void Release() const + { + UNREFERENCED_OACR(this); + } }; struct BaseClass { - virtual int GetInt() noexcept { return 0; } + virtual int GetInt() noexcept + { + return 0; + } }; -struct Derived final - : public BaseClass +struct Derived final : public BaseClass { - int i; + int i; - int GetInt() noexcept override { return i; } + int GetInt() noexcept override + { + return i; + } }; static Derived& DerivedFromBaseClass(BaseClass& baseClass) noexcept { - static Derived derived; + static Derived derived; - derived.i = baseClass.GetInt(); - return derived; + derived.i = baseClass.GetInt(); + return derived; } } // namespace FunctorTestsCommon diff --git a/libs/memoryApi/include/core/memoryApi.h b/libs/memoryApi/include/core/memoryApi.h index 9bf473b..0c47e81 100644 --- a/libs/memoryApi/include/core/memoryApi.h +++ b/libs/memoryApi/include/core/memoryApi.h @@ -21,7 +21,7 @@ See MsoMemory.h for information about operator new. #ifndef MsoSetLazyLeakDetection #ifdef DEBUG LIBLET_PUBLICAPI_EX("android", "win") MSOAPI_(void) MsoSetLazyLeakDetection(const void* pv) noexcept; -#else +#else #define MsoSetLazyLeakDetection(pv) 0 #endif // DEBUG #endif // !MsoSetLazyLeakDetection @@ -29,89 +29,87 @@ LIBLET_PUBLICAPI_EX("android", "win") MSOAPI_(void) MsoSetLazyLeakDetection(cons #ifndef MsoSetShutdownLeakDetection #ifdef DEBUG LIBLET_PUBLICAPI_EX("android", "win") MSOAPI_(void) MsoSetShutdownLeakDetection(const void* pv) noexcept; -#else +#else #define MsoSetShutdownLeakDetection(pv) 0 #endif // DEBUG #endif // !MsoSetShutdownLeakDetection #ifdef __cplusplus -namespace Mso { - namespace LibletAPI { - struct ILibletMemoryMarking - { - virtual void MarkLiblets(intptr_t lParam) noexcept = 0; - }; - } -} +namespace Mso { namespace LibletAPI { +struct ILibletMemoryMarking +{ + virtual void MarkLiblets(intptr_t lParam) noexcept = 0; +}; +}} // namespace Mso::LibletAPI #ifdef DEBUG struct IMsoMemHeap; -LIBLET_PUBLICAPI_EX("android", "win") MSOAPI_(BOOL) FMemHeapMsoSaveBeHost(void* pinst, LPARAM lParam, const void* pvBlock, LONG_PTR cb, IMsoMemHeap* pmmh) MSONOEXCEPT; +LIBLET_PUBLICAPI_EX("android", "win") +MSOAPI_(BOOL) + FMemHeapMsoSaveBeHost(void* pinst, LPARAM lParam, const void* pvBlock, LONG_PTR cb, IMsoMemHeap* pmmh) MSONOEXCEPT; LIBLET_PUBLICAPI_EX("android", "win") MSOAPI_(void) MsoCheckShutdownLeaks() noexcept; LIBLET_PUBLICAPI_EX("win") MSOAPI_(void) HeapEnableLeakTracking(bool isEnabled); LIBLET_PUBLICAPI_EX("win") MSOAPI_(void) MsoBeforeThreadTerminatesThreaded(DWORD mainThreadId) noexcept; #endif LIBLET_PUBLICAPI_EX("android", "win") __declspec(noreturn) void ThrowOOM(); -namespace Mso { - namespace Memory { +namespace Mso { namespace Memory { #ifdef DEBUG - LIBLET_PUBLICAPI_EX("android", "win") MSOCPPAPI_(void) RegisterCallback(Mso::LibletAPI::ILibletMemoryMarking& libletCallback) noexcept; - LIBLET_PUBLICAPI_EX("android", "win") MSOCPPAPI_(void) UnregisterCallback(Mso::LibletAPI::ILibletMemoryMarking& libletCallback) noexcept; +LIBLET_PUBLICAPI_EX("android", "win") +MSOCPPAPI_(void) RegisterCallback(Mso::LibletAPI::ILibletMemoryMarking& libletCallback) noexcept; +LIBLET_PUBLICAPI_EX("android", "win") +MSOCPPAPI_(void) UnregisterCallback(Mso::LibletAPI::ILibletMemoryMarking& libletCallback) noexcept; - /** - Helper class to register arbitrary callback for memory marking - */ - struct RegisterMarkMemoryCallback : public Mso::LibletAPI::ILibletMemoryMarking - { - using MarkMemHandler = std::add_pointer_t; +/** +Helper class to register arbitrary callback for memory marking +*/ +struct RegisterMarkMemoryCallback : public Mso::LibletAPI::ILibletMemoryMarking +{ + using MarkMemHandler = std::add_pointer_t; - DECLARE_COPYCONSTR_AND_ASSIGNMENT(RegisterMarkMemoryCallback); - RegisterMarkMemoryCallback(MarkMemHandler handler) noexcept - : m_handler(handler) - { - RegisterCallback(*this); - } + DECLARE_COPYCONSTR_AND_ASSIGNMENT(RegisterMarkMemoryCallback); + RegisterMarkMemoryCallback(MarkMemHandler handler) noexcept : m_handler(handler) + { + RegisterCallback(*this); + } - virtual ~RegisterMarkMemoryCallback() noexcept - { - UnregisterCallback(*this); - } + virtual ~RegisterMarkMemoryCallback() noexcept + { + UnregisterCallback(*this); + } - void MarkLiblets(intptr_t lParam) noexcept override - { - m_handler(lParam); - } + void MarkLiblets(intptr_t lParam) noexcept override + { + m_handler(lParam); + } - private: - MarkMemHandler m_handler; - }; +private: + MarkMemHandler m_handler; +}; #endif - } -} +}} // namespace Mso::Memory #ifdef DEBUG -namespace Mso { - namespace Memory { - // Legacy API - inline _Ret_notnull_ _Post_writable_byte_size_(cb) void* Allocate(size_t cb FILELINEPARAMSUNUSED) noexcept - { - return AllocateEx(cb, 0); - } - - // Legacy API - inline _Ret_maybenull_ _Post_writable_byte_size_(cb) void* AllocateEx(size_t cb, DWORD allocFlags FILELINEPARAMSUNUSED) noexcept - { - return AllocateEx(cb, allocFlags); - } - - // Legacy API - inline _Ret_maybenull_ void* Reallocate(_Inout_ void** ppv, size_t cb FILELINEPARAMSUNUSED) noexcept - { - return Reallocate(ppv, cb); - } - } +namespace Mso { namespace Memory { +// Legacy API +inline _Ret_notnull_ _Post_writable_byte_size_(cb) void* Allocate(size_t cb FILELINEPARAMSUNUSED) noexcept +{ + return AllocateEx(cb, 0); } + +// Legacy API +inline _Ret_maybenull_ _Post_writable_byte_size_( + cb) void* AllocateEx(size_t cb, DWORD allocFlags FILELINEPARAMSUNUSED) noexcept +{ + return AllocateEx(cb, allocFlags); +} + +// Legacy API +inline _Ret_maybenull_ void* Reallocate(_Inout_ void** ppv, size_t cb FILELINEPARAMSUNUSED) noexcept +{ + return Reallocate(ppv, cb); +} +}} // namespace Mso::Memory #endif #endif diff --git a/libs/memoryApi/include/memoryApi/leakDetection.h b/libs/memoryApi/include/memoryApi/leakDetection.h index 14afe76..833ddad 100644 --- a/libs/memoryApi/include/memoryApi/leakDetection.h +++ b/libs/memoryApi/include/memoryApi/leakDetection.h @@ -2,20 +2,20 @@ // Licensed under the MIT license. /** - Deprecated APIs related to leak detection + Deprecated APIs related to leak detection */ #pragma once #include /** - When this object is active, allocations on this thread are marked as - needing to be cleaned up by shutdown. + When this object is active, allocations on this thread are marked as + needing to be cleaned up by shutdown. */ using MsoDebugShutdownLazyScope = Mso::Memory::AutoShutdownLeakScope; /** - When this object is active, allocations on this thread are not tracked - for leak detection. Typically used when the memory lifetime is the life of - the DLL or is managed by an external dependency. + When this object is active, allocations on this thread are not tracked + for leak detection. Typically used when the memory lifetime is the life of + the DLL or is managed by an external dependency. */ using MsoDebugLazyScope = Mso::Memory::AutoIgnoreLeakScope; diff --git a/libs/memoryApi/include/memoryApi/memoryApi.h b/libs/memoryApi/include/memoryApi/memoryApi.h index 36e9e2d..e9fec23 100644 --- a/libs/memoryApi/include/memoryApi/memoryApi.h +++ b/libs/memoryApi/include/memoryApi/memoryApi.h @@ -28,421 +28,421 @@ See MsoMemory.h for information about operator new. #undef New #include -namespace Mso { - namespace Memory { - namespace Details { - template - struct Emplacer - { - template - static void Place(_Inout_updates_bytes_all_(sizeof(T)) void* mem, Args&&... args) noexcept - { - new (mem) T(std::forward(args)...); - } - }; +namespace Mso { namespace Memory { +namespace Details { +template +struct Emplacer +{ + template + static void Place(_Inout_updates_bytes_all_(sizeof(T)) void* mem, Args&&... args) noexcept + { + new (mem) T(std::forward(args)...); + } +}; - template - struct Emplacer < T[N] > - { - template - static void Place(void* mem, Args&&... args) - { - new (mem) T[N] - { - std::forward(args)... - }; - } - }; +template +struct Emplacer +{ + template + static void Place(void* mem, Args&&... args) + { + new (mem) T[N]{std::forward(args)...}; + } +}; - template - struct Destructor - { - static void Destruct(T&) noexcept { /* noop */ } - }; +template +struct Destructor +{ + static void Destruct(T&) noexcept + { /* noop */ + } +}; - template - struct Destructor < T, - typename std::enable_if::value && !std::is_pod::value>::type > - { - static void Destruct(T& obj) noexcept - { - UNREFERENCED_PARAMETER(obj); - obj.~T(); - } - }; - } // Details - - /** - Mso::Memory::AllocFlags - */ - namespace AllocFlags { - enum Enum : unsigned int - { - // check this memory during shutdown leak detection - ShutdownLeak = 0x0001, - - // ignore this memory during leak detection - IgnoreLeak = 0x0002, - - // track this memory using memory marking / idle time leak detection - MarkingLeak = 0x0004, - }; - }; - - /** - Return a new allocation of the requested size (cb) - Returns nullptr on failure - */ - LIBLET_PUBLICAPI_EX("win", "android") _Ret_maybenull_ _Post_writable_byte_size_(cb) void* AllocateEx(size_t cb, DWORD allocFlags) noexcept; - - /** - Return a new allocation of the requested size (cb) - Returns nullptr on failure - */ - inline _Ret_maybenull_ _Post_writable_byte_size_(cb) void* Allocate(size_t cb) noexcept - { - return Mso::Memory::AllocateEx(cb, 0); - } - - /** - Reallocate an existing allocation to a new size - Returns nullptr on failure - TODO: Do we need ReallocateEx? Only if allocFlags grows. - */ - LIBLET_PUBLICAPI_EX("win", "android") _Ret_maybenull_ void* Reallocate(_Inout_ void** ppv, size_t cb) noexcept; - - template - _Ret_maybenull_ T* Reallocate(T* pT, size_t cb) noexcept - { - return reinterpret_cast(Reallocate(reinterpret_cast(&pT), cb)); - } - - /** - Return the allocation size of a given pointer - */ - LIBLET_PUBLICAPI_EX("win", "android") size_t AllocationSize(_In_opt_ const void* pv) noexcept; - - /** - Release a previously allocated block of memory - */ - LIBLET_PUBLICAPI_EX("win", "android") void Free(_Pre_maybenull_ _Post_invalid_ void* pv) noexcept; - - /** - Disambiguator used to ensure a throwing new - new (Mso::Memory::throwNew) Zoo(); - */ - OACR_WARNING_SUPPRESS(SPECIFY_SELECTANY, "Not needed for marker type") - static const struct throwNew_t - { - throwNew_t() noexcept = default; - } throwNew; - - /** - Disambiguator used to ensure a crashing new - new (Mso::Memory::failFast) Zoo(); - */ - OACR_WARNING_SUPPRESS(SPECIFY_SELECTANY, "Not needed for marker type") - static const struct failFast_t - { - failFast_t() noexcept = default; - } failFast; - - /** - Construct a object of type `T` stored at `mem`. - - Arguments are forwarded to constructor of `T`. - */ - template - static void Place(__inout_bcount(sizeof(T)) void* mem, Args&&... args) - { - Details::Emplacer::Place(mem, std::forward(args)...); - } - - /** - Manually destruct an object of type `T`. - */ - template ::value>::type> - static void Destruct(T& obj) noexcept - { - Details::Destructor::Destruct(obj); - } - - /** - Manually destruct a `T[N]`. - - Destructs contents of the array in reverse order. - */ - template - static void Destruct(T(&obj)[N]) noexcept - { - size_t i = N; - while (i--) - Destruct(obj[i]); - } - } // Memory -} // Mso - -namespace Mso { -namespace Memory { -namespace FailFast { - /** - Return a new allocation of the requested size (cb) - Never returns nullptr - */ - _Ret_maybenull_ _Post_writable_byte_size_(cb) inline void* AllocateEx(size_t cb, DWORD allocFlags) noexcept - { - auto pv = Mso::Memory::AllocateEx(cb, allocFlags); - if (pv == nullptr) - CrashWithRecoveryOnOOM(); - return pv; - } - - _Ret_maybenull_ _Post_writable_byte_size_(cb) inline void* Allocate(size_t cb) noexcept - { - return AllocateEx(cb, 0); - } -} // FailFast -} // Memory -} // Mso - -namespace Mso { -namespace Memory { -namespace NoThrow { +template +struct Destructor::value && !std::is_pod::value>::type> +{ + static void Destruct(T& obj) noexcept + { + UNREFERENCED_PARAMETER(obj); + obj.~T(); + } +}; +} // namespace Details /** - non-throwing operator new using memory-marking leak detection - new (Mso::Memory::NoThrow::MarkingLeak) Zoo(); +Mso::Memory::AllocFlags +*/ +namespace AllocFlags { +enum Enum : unsigned int +{ + // check this memory during shutdown leak detection + ShutdownLeak = 0x0001, + + // ignore this memory during leak detection + IgnoreLeak = 0x0002, + + // track this memory using memory marking / idle time leak detection + MarkingLeak = 0x0004, +}; +}; + +/** +Return a new allocation of the requested size (cb) +Returns nullptr on failure +*/ +LIBLET_PUBLICAPI_EX("win", "android") +_Ret_maybenull_ _Post_writable_byte_size_(cb) void* AllocateEx(size_t cb, DWORD allocFlags) noexcept; + +/** +Return a new allocation of the requested size (cb) +Returns nullptr on failure +*/ +inline _Ret_maybenull_ _Post_writable_byte_size_(cb) void* Allocate(size_t cb) noexcept +{ + return Mso::Memory::AllocateEx(cb, 0); +} + +/** +Reallocate an existing allocation to a new size +Returns nullptr on failure +TODO: Do we need ReallocateEx? Only if allocFlags grows. +*/ +LIBLET_PUBLICAPI_EX("win", "android") _Ret_maybenull_ void* Reallocate(_Inout_ void** ppv, size_t cb) noexcept; + +template +_Ret_maybenull_ T* Reallocate(T* pT, size_t cb) noexcept +{ + return reinterpret_cast(Reallocate(reinterpret_cast(&pT), cb)); +} + +/** +Return the allocation size of a given pointer +*/ +LIBLET_PUBLICAPI_EX("win", "android") size_t AllocationSize(_In_opt_ const void* pv) noexcept; + +/** +Release a previously allocated block of memory +*/ +LIBLET_PUBLICAPI_EX("win", "android") void Free(_Pre_maybenull_ _Post_invalid_ void* pv) noexcept; + +/** +Disambiguator used to ensure a throwing new +new (Mso::Memory::throwNew) Zoo(); +*/ +OACR_WARNING_SUPPRESS(SPECIFY_SELECTANY, "Not needed for marker type") +static const struct throwNew_t +{ + throwNew_t() noexcept = default; +} throwNew; + +/** +Disambiguator used to ensure a crashing new +new (Mso::Memory::failFast) Zoo(); +*/ +OACR_WARNING_SUPPRESS(SPECIFY_SELECTANY, "Not needed for marker type") +static const struct failFast_t +{ + failFast_t() noexcept = default; +} failFast; + +/** +Construct a object of type `T` stored at `mem`. + +Arguments are forwarded to constructor of `T`. +*/ +template +static void Place(__inout_bcount(sizeof(T)) void* mem, Args&&... args) +{ + Details::Emplacer::Place(mem, std::forward(args)...); +} + +/** +Manually destruct an object of type `T`. +*/ +template ::value>::type> +static void Destruct(T& obj) noexcept +{ + Details::Destructor::Destruct(obj); +} + +/** +Manually destruct a `T[N]`. + +Destructs contents of the array in reverse order. +*/ +template +static void Destruct(T (&obj)[N]) noexcept +{ + size_t i = N; + while (i--) + Destruct(obj[i]); +} +}} // namespace Mso::Memory + +namespace Mso { namespace Memory { namespace FailFast { +/** +Return a new allocation of the requested size (cb) +Never returns nullptr +*/ +_Ret_maybenull_ _Post_writable_byte_size_(cb) inline void* AllocateEx(size_t cb, DWORD allocFlags) noexcept +{ + auto pv = Mso::Memory::AllocateEx(cb, allocFlags); + if (pv == nullptr) + CrashWithRecoveryOnOOM(); + return pv; +} + +_Ret_maybenull_ _Post_writable_byte_size_(cb) inline void* Allocate(size_t cb) noexcept +{ + return AllocateEx(cb, 0); +} +}}} // namespace Mso::Memory::FailFast + +namespace Mso { namespace Memory { namespace NoThrow { + +/** + non-throwing operator new using memory-marking leak detection + new (Mso::Memory::NoThrow::MarkingLeak) Zoo(); */ OACR_WARNING_SUPPRESS(SPECIFY_SELECTANY, "Not needed for marker type") static const struct MarkingLeak_t { - MarkingLeak_t() noexcept = default; + MarkingLeak_t() noexcept = default; } MarkingLeak; -} // NoThrow -} // Memory -} // Mso +}}} // namespace Mso::Memory::NoThrow -namespace Mso { - namespace Memory { - namespace Throw { +namespace Mso { namespace Memory { namespace Throw { #pragma warning(push) -#pragma warning(disable:4100) - /** - Mso::Memory::Throw::New(args) +#pragma warning(disable : 4100) +/** +Mso::Memory::Throw::New(args) - Allocates object T by passing args to its constructor. - */ - template - OACR_WARNING_SUPPRESS( NULL_ON_NON_POINTER, "false positive" ) - _Ret_notnull_ T* New(TArgs&&... t) - { - Debug(Mso::Memory::AutoShutdownLeakScope scope); - T* pT = new(std::nothrow) T(std::forward(t)...); - if (pT == nullptr) - throw std::bad_alloc(); - return pT; - } +Allocates object T by passing args to its constructor. +*/ +template +OACR_WARNING_SUPPRESS(NULL_ON_NON_POINTER, "false positive") +_Ret_notnull_ T* New(TArgs&&... t) +{ + Debug(Mso::Memory::AutoShutdownLeakScope scope); + T* pT = new (std::nothrow) T(std::forward(t)...); + if (pT == nullptr) + throw std::bad_alloc(); + return pT; +} #pragma warning(pop) - } // Throw - } // Memory -} // Mso +}}} // namespace Mso::Memory::Throw namespace Mso { - /** - Frees memory allocated by Mso::Memory - */ - template< typename T > struct MemoryPtrHelper - { - static void Free(T* pT) noexcept { Mso::Memory::Free(pT); } - }; +/** +Frees memory allocated by Mso::Memory +*/ +template +struct MemoryPtrHelper +{ + static void Free(T* pT) noexcept + { + Mso::Memory::Free(pT); + } +}; - /** - Mso::MemoryPtr +/** +Mso::MemoryPtr - Smart pointer for memory allocated by Mso::Memory. - Suitable for raw memory or vanilla structs. - Does not run copy constructors or destructors. +Smart pointer for memory allocated by Mso::Memory. +Suitable for raw memory or vanilla structs. +Does not run copy constructors or destructors. - The equals operator is purposely left out. Use the c'tor or Attach(). +The equals operator is purposely left out. Use the c'tor or Attach(). - Mso::MemoryPtr pFoo; // equivalent to BYTE* pFoo; - */ - template< typename T, DWORD allocFlags = 0 > class MemoryPtr : public Mso::THolder< T*, MemoryPtrHelper< T > > - { - typedef Mso::THolder< T*, MemoryPtrHelper< T > > Super; +Mso::MemoryPtr pFoo; // equivalent to BYTE* pFoo; +*/ +template +class MemoryPtr : public Mso::THolder> +{ + typedef Mso::THolder> Super; - public: - MemoryPtr() noexcept {} - explicit MemoryPtr(_In_opt_ T* pT) noexcept { this->Attach(pT); } // Takes ownership - IMPLEMENT_THOLDER_RVALUE_REFS_(MemoryPtr, Super); +public: + MemoryPtr() noexcept {} + explicit MemoryPtr(_In_opt_ T* pT) noexcept + { + this->Attach(pT); + } // Takes ownership + IMPLEMENT_THOLDER_RVALUE_REFS_(MemoryPtr, Super); - /** - AllocBytes + /** + AllocBytes - Allocate space for the given number of bytes. - On success, any previously held data is replaced. - Returns false on OOM / overflow. + Allocate space for the given number of bytes. + On success, any previously held data is replaced. + Returns false on OOM / overflow. - AllocElem-variants are strongly preferred to avoid integer overflows. + AllocElem-variants are strongly preferred to avoid integer overflows. - Mso::MemoryPtr pbFoo; - if (pbFoo.AllocBytes(cbData)) { ... } - */ - bool AllocBytes(size_t cb) noexcept - { - T* pT = static_cast(Mso::Memory::AllocateEx(cb, allocFlags)); - if (pT != nullptr) - this->Attach(pT); - return (pT != nullptr); - } + Mso::MemoryPtr pbFoo; + if (pbFoo.AllocBytes(cbData)) { ... } + */ + bool AllocBytes(size_t cb) noexcept + { + T* pT = static_cast(Mso::Memory::AllocateEx(cb, allocFlags)); + if (pT != nullptr) + this->Attach(pT); + return (pT != nullptr); + } - /** - AllocElem + /** + AllocElem - Allocate space for cElements + cExtra instances. - On success, any previously held data is replaced. - Optional out parameters to receive the number of elements/bytes allocated - Returns false on OOM / overflow. + Allocate space for cElements + cExtra instances. + On success, any previously held data is replaced. + Optional out parameters to receive the number of elements/bytes allocated + Returns false on OOM / overflow. - Mso::MemoryPtr wzFoo; - size_t cchFoo = 0; - if (wzFoo.AllocElemCb(cch, 1, &cchFoo)) { ... } - */ - bool AllocElem(size_t cElements, size_t cExtra = 0, _Out_opt_ size_t* pcElements = nullptr, _Out_opt_ size_t* pcbAlloc = nullptr) noexcept - { - // TODO: size_t cbAlloc = (msl::utilities::SafeInt(cElements) +cExtra) * sizeof(T); - size_t cbAlloc = (cElements + cExtra) * sizeof(T); - bool fRet = AllocBytes(cbAlloc); - if (pcElements != nullptr) - *pcElements = (fRet ? cbAlloc / sizeof(T) : 0); - if (pcbAlloc != nullptr) - *pcbAlloc = (fRet ? cbAlloc : 0); - return fRet; - } + Mso::MemoryPtr wzFoo; + size_t cchFoo = 0; + if (wzFoo.AllocElemCb(cch, 1, &cchFoo)) { ... } + */ + bool AllocElem( + size_t cElements, + size_t cExtra = 0, + _Out_opt_ size_t* pcElements = nullptr, + _Out_opt_ size_t* pcbAlloc = nullptr) noexcept + { + // TODO: size_t cbAlloc = (msl::utilities::SafeInt(cElements) +cExtra) * sizeof(T); + size_t cbAlloc = (cElements + cExtra) * sizeof(T); + bool fRet = AllocBytes(cbAlloc); + if (pcElements != nullptr) + *pcElements = (fRet ? cbAlloc / sizeof(T) : 0); + if (pcbAlloc != nullptr) + *pcbAlloc = (fRet ? cbAlloc : 0); + return fRet; + } - /** - AllocOne + /** + AllocOne - Allocate space for 1 instance. - On success, any previously held data is replaced. - Returns false on OOM / overflow. + Allocate space for 1 instance. + On success, any previously held data is replaced. + Returns false on OOM / overflow. - Mso::MemoryPtr pFoo; - if (pFoo.AllocOne()) { ... } - */ - bool AllocOne() noexcept - { - return AllocElem(1); - } + Mso::MemoryPtr pFoo; + if (pFoo.AllocOne()) { ... } + */ + bool AllocOne() noexcept + { + return AllocElem(1); + } - // TODO: Does it make sense for CallocElemCb? See if there is need. + // TODO: Does it make sense for CallocElemCb? See if there is need. - /** - ReallocBytes + /** + ReallocBytes - Reallocate the exact number of bytes. - Returns false on OOM / overflow. + Reallocate the exact number of bytes. + Returns false on OOM / overflow. - ReallocElem is strongly preferred. - */ - bool ReallocBytes(size_t cb) noexcept - { - const T* pT = static_cast(Mso::Memory::Reallocate(reinterpret_cast(&this->m_pT), cb)); - return (pT != nullptr); - } + ReallocElem is strongly preferred. + */ + bool ReallocBytes(size_t cb) noexcept + { + const T* pT = static_cast(Mso::Memory::Reallocate(reinterpret_cast(&this->m_pT), cb)); + return (pT != nullptr); + } - /** - ReallocElem + /** + ReallocElem - Reallocate space for cElements + cExtra instances. - Optional out parameters to receive the number of elements/bytes allocated - Returns false on OOM / overflow. - */ - bool ReallocElem(size_t cElements, size_t cExtra = 0, _Out_opt_ size_t* pcElements = nullptr, _Out_opt_ size_t* pcbAlloc = nullptr) noexcept - { - // TODO: size_t cbAlloc = (msl::utilities::SafeInt(cElements) +cExtra) * sizeof(T); - size_t cbAlloc = (cElements + cExtra) * sizeof(T); - bool fRet = ReallocBytes(cbAlloc); - if (pcElements != nullptr) - *pcElements = (fRet ? cbAlloc / sizeof(T) : 0); - if (pcbAlloc != nullptr) - *pcbAlloc = (fRet ? cbAlloc : 0); - return fRet; - } + Reallocate space for cElements + cExtra instances. + Optional out parameters to receive the number of elements/bytes allocated + Returns false on OOM / overflow. + */ + bool ReallocElem( + size_t cElements, + size_t cExtra = 0, + _Out_opt_ size_t* pcElements = nullptr, + _Out_opt_ size_t* pcbAlloc = nullptr) noexcept + { + // TODO: size_t cbAlloc = (msl::utilities::SafeInt(cElements) +cExtra) * sizeof(T); + size_t cbAlloc = (cElements + cExtra) * sizeof(T); + bool fRet = ReallocBytes(cbAlloc); + if (pcElements != nullptr) + *pcElements = (fRet ? cbAlloc / sizeof(T) : 0); + if (pcbAlloc != nullptr) + *pcbAlloc = (fRet ? cbAlloc : 0); + return fRet; + } - /** - CloneBytes + /** + CloneBytes - Allocates a new buffer and copies the data into it. - On success, any previously held data is replaced. - Returns false on OOM / overflow. + Allocates a new buffer and copies the data into it. + On success, any previously held data is replaced. + Returns false on OOM / overflow. - CloneElem-variants are strongly preferred to avoid integer overflow. - FUTURE: I could add cbExtra parameter if it makes sense. + CloneElem-variants are strongly preferred to avoid integer overflow. + FUTURE: I could add cbExtra parameter if it makes sense. - Mso::MemoryPtr pbFoo; - if (pbFoo.CloneBytes(pbSrc, cbSrc)) { ... } - */ - bool CloneBytes(_In_opt_bytecount_(cb) const T* pT, size_t cb) noexcept - { - if (pT != nullptr) - { - Mso::MemoryPtr pNew; - if (pNew.AllocBytes(cb)) - { - memcpy_s(pNew.Get(), cb, pT, cb); - this->Swap(pNew); - return true; - } - } + Mso::MemoryPtr pbFoo; + if (pbFoo.CloneBytes(pbSrc, cbSrc)) { ... } + */ + bool CloneBytes(_In_opt_bytecount_(cb) const T* pT, size_t cb) noexcept + { + if (pT != nullptr) + { + Mso::MemoryPtr pNew; + if (pNew.AllocBytes(cb)) + { + memcpy_s(pNew.Get(), cb, pT, cb); + this->Swap(pNew); + return true; + } + } - return false; - } + return false; + } - /** - CloneElem + /** + CloneElem - Allocate space and copies cElements instances from the source. - On success, any previously held data is replaced. - Returns false on OOM / overflow. + Allocate space and copies cElements instances from the source. + On success, any previously held data is replaced. + Returns false on OOM / overflow. - Mso::MemoryPtr rgFooData; - if (rgFooData.CloneElem(rgFooDataSrc, cFooDataSrc) { ... } - */ - bool CloneElem(_In_opt_count_(cElements) const T* pT, size_t cElements) noexcept - { - // TODO: size_t cbAlloc = msl::utilities::SafeInt(cElements) * sizeof(T); - size_t cbAlloc = (cElements)* sizeof(T); - return CloneBytes(pT, cbAlloc); - } + Mso::MemoryPtr rgFooData; + if (rgFooData.CloneElem(rgFooDataSrc, cFooDataSrc) { ... } + */ + bool CloneElem(_In_opt_count_(cElements) const T* pT, size_t cElements) noexcept + { + // TODO: size_t cbAlloc = msl::utilities::SafeInt(cElements) * sizeof(T); + size_t cbAlloc = (cElements) * sizeof(T); + return CloneBytes(pT, cbAlloc); + } - /** - CloneOne + /** + CloneOne - Allocates space and copies 1 instance from the source. - Any previously held data is replaced on success. + Allocates space and copies 1 instance from the source. + Any previously held data is replaced on success. - Mso::MemoryPtr pFoo; - if (pFoo.AllocOne(pFooSrc)) { ... } - */ - bool CloneOne(_In_opt_count_(1) const T* pT) noexcept - { - return CloneElem(pT, 1); - } + Mso::MemoryPtr pFoo; + if (pFoo.AllocOne(pFooSrc)) { ... } + */ + bool CloneOne(_In_opt_count_(1) const T* pT) noexcept + { + return CloneElem(pT, 1); + } #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY - T& operator*() const noexcept - { - return *this->Get(); - } + T& operator*() const noexcept + { + return *this->Get(); + } #endif - private: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(MemoryPtr); - }; -} // Mso +private: + DECLARE_COPYCONSTR_AND_ASSIGNMENT(MemoryPtr); +}; +} // namespace Mso #pragma pop_macro("New") #pragma pop_macro("new") diff --git a/libs/memoryApi/include/memoryApi/threadLocalUniquePtr.h b/libs/memoryApi/include/memoryApi/threadLocalUniquePtr.h index 4fb306e..7d93e84 100644 --- a/libs/memoryApi/include/memoryApi/threadLocalUniquePtr.h +++ b/libs/memoryApi/include/memoryApi/threadLocalUniquePtr.h @@ -13,68 +13,65 @@ namespace Mso { Acts like unique_ptr for a thread-local variable, automatically deletes on thread-exit. Use as static variable since this object lifetime controls the backing thread-storage. */ -template> +template > class threadlocal_unique_ptr : private Mso::ThreadLocal { - using Super = Mso::ThreadLocal; + using Super = Mso::ThreadLocal; public: - threadlocal_unique_ptr() noexcept : Super(Delete) - { - } + threadlocal_unique_ptr() noexcept : Super(Delete) {} - explicit operator bool() const noexcept - { - return get() != nullptr; - } + explicit operator bool() const noexcept + { + return get() != nullptr; + } - T* operator ->() const noexcept - { - return get(); - } + T* operator->() const noexcept + { + return get(); + } - T* get() const noexcept - { - return Super::GetValue(); - } + T* get() const noexcept + { + return Super::GetValue(); + } - T& getOrCreate() noexcept - { - auto t = get(); - if (!t) - { + T& getOrCreate() noexcept + { + auto t = get(); + if (!t) + { #ifdef DEBUG - Mso::Memory::AutoIgnoreLeakScope ignoreTlsVar; + Mso::Memory::AutoIgnoreLeakScope ignoreTlsVar; #endif - t = new T(); - reset(t); - } + t = new T(); + reset(t); + } - return *t; - } + return *t; + } - void reset(T* t) noexcept - { - Delete(release()); - Super::SetValue(t); - } + void reset(T* t) noexcept + { + Delete(release()); + Super::SetValue(t); + } - T* release() noexcept - { - auto t = get(); - Super::SetValue(nullptr); - return t; - } + T* release() noexcept + { + auto t = get(); + Super::SetValue(nullptr); + return t; + } private: - static void __stdcall Delete(T* t) noexcept - { - Deleter()(t); - } + static void __stdcall Delete(T* t) noexcept + { + Deleter()(t); + } }; -} // Mso +} // namespace Mso #endif // C++ #endif // _CPPEXTENSIONS_THREADLOCALUNIQUEPTR_H_ - diff --git a/libs/memoryApi/include/memoryLeakScope/memoryLeakScope.h b/libs/memoryApi/include/memoryLeakScope/memoryLeakScope.h index 0980fbe..52ce49e 100644 --- a/libs/memoryApi/include/memoryLeakScope/memoryLeakScope.h +++ b/libs/memoryApi/include/memoryLeakScope/memoryLeakScope.h @@ -7,22 +7,24 @@ #ifdef __cplusplus #include -namespace Mso { -namespace Memory { +namespace Mso { namespace Memory { /** - Is the ShutdownLeakScope currently active? + Is the ShutdownLeakScope currently active? */ #ifdef DEBUG LIBLET_PUBLICAPI bool IsInShutdownLeakScope() noexcept; #else -inline bool IsInShutdownLeakScope() noexcept { return false; } +inline bool IsInShutdownLeakScope() noexcept +{ + return false; +} #endif /** - Enter the scope so allocations on this thread should be marked for shutdown leak detection. - Scope can be entered a limited number of times. - Frames to skip is used to track which caller address is associated with this Enter. + Enter the scope so allocations on this thread should be marked for shutdown leak detection. + Scope can be entered a limited number of times. + Frames to skip is used to track which caller address is associated with this Enter. */ #ifdef DEBUG LIBLET_PUBLICAPI void EnterShutdownLeakScope(unsigned int framesToSkip = 0) noexcept; @@ -31,7 +33,7 @@ inline void EnterShutdownLeakScope(unsigned int /*framesToSkip*/ = 0) noexcept { #endif /** - Leave + Leave */ #ifdef DEBUG LIBLET_PUBLICAPI void LeaveShutdownLeakScope() noexcept; @@ -40,18 +42,21 @@ inline void LeaveShutdownLeakScope() noexcept {} #endif /** - Is the IgnoreLeakScope currently active? + Is the IgnoreLeakScope currently active? */ #ifdef DEBUG LIBLET_PUBLICAPI bool IsInIgnoreLeakScope() noexcept; #else -inline bool IsInIgnoreLeakScope() noexcept { return false; } +inline bool IsInIgnoreLeakScope() noexcept +{ + return false; +} #endif /** - Enter the scope so allocations on this thread should be ignored for leak detection. - Scope can be entered a limited number of times. - Frames to skip is used to track which caller address is associated with this Enter. + Enter the scope so allocations on this thread should be ignored for leak detection. + Scope can be entered a limited number of times. + Frames to skip is used to track which caller address is associated with this Enter. */ #ifdef DEBUG LIBLET_PUBLICAPI void EnterIgnoreLeakScope(unsigned int framesToSkip = 0) noexcept; @@ -60,7 +65,7 @@ inline void EnterIgnoreLeakScope(unsigned int /*framesToSkip*/ = 0) noexcept {} #endif /** - Leave + Leave */ #ifdef DEBUG LIBLET_PUBLICAPI void LeaveIgnoreLeakScope() noexcept; @@ -70,38 +75,37 @@ inline void LeaveIgnoreLeakScope() noexcept {} struct AutoShutdownLeakScope { - AutoShutdownLeakScope(unsigned int framesToSkip = 0) noexcept - { - EnterShutdownLeakScope(++framesToSkip); - } - - AutoShutdownLeakScope(const AutoShutdownLeakScope& /*other*/) noexcept : AutoShutdownLeakScope(1) {} - AutoShutdownLeakScope(AutoShutdownLeakScope&& /*other*/) noexcept : AutoShutdownLeakScope(1) {} + AutoShutdownLeakScope(unsigned int framesToSkip = 0) noexcept + { + EnterShutdownLeakScope(++framesToSkip); + } - ~AutoShutdownLeakScope() noexcept - { - LeaveShutdownLeakScope(); - } + AutoShutdownLeakScope(const AutoShutdownLeakScope& /*other*/) noexcept : AutoShutdownLeakScope(1) {} + AutoShutdownLeakScope(AutoShutdownLeakScope&& /*other*/) noexcept : AutoShutdownLeakScope(1) {} + + ~AutoShutdownLeakScope() noexcept + { + LeaveShutdownLeakScope(); + } }; struct AutoIgnoreLeakScope { - AutoIgnoreLeakScope(unsigned int framesToSkip = 0) noexcept - { - EnterIgnoreLeakScope(++framesToSkip); - } + AutoIgnoreLeakScope(unsigned int framesToSkip = 0) noexcept + { + EnterIgnoreLeakScope(++framesToSkip); + } - AutoIgnoreLeakScope(const AutoIgnoreLeakScope& /*other*/) noexcept : AutoIgnoreLeakScope(1) {} - AutoIgnoreLeakScope(AutoIgnoreLeakScope&& /*other*/) noexcept : AutoIgnoreLeakScope(1) {} + AutoIgnoreLeakScope(const AutoIgnoreLeakScope& /*other*/) noexcept : AutoIgnoreLeakScope(1) {} + AutoIgnoreLeakScope(AutoIgnoreLeakScope&& /*other*/) noexcept : AutoIgnoreLeakScope(1) {} - ~AutoIgnoreLeakScope() noexcept - { - LeaveIgnoreLeakScope(); - } + ~AutoIgnoreLeakScope() noexcept + { + LeaveIgnoreLeakScope(); + } }; -} -} // Mso::Memory +}} // namespace Mso::Memory #endif // C++ #endif // LIBLET_MEMORYAPI_SCOPE diff --git a/libs/memoryApi/include/safeAlloct.h b/libs/memoryApi/include/safeAlloct.h index 5beb40d..5667cd8 100644 --- a/libs/memoryApi/include/safeAlloct.h +++ b/libs/memoryApi/include/safeAlloct.h @@ -8,98 +8,101 @@ #include //#include /* -* MsoCbBufSizeT -* This function returns the bytes needed to allocate a buffer for (cElements + cExtra) -* instances of type T. This is a low level function, and typical usage would be to call -* one of the wrappers that deal with (for example) WCHAR arrays. -* -* Note: Strictly speaking, this isn't an exported MSO function, as it's instantiated by -* the caller, and simply picked up from the header. -* -* Arguments: -* cElements - the number of elements needed -* cExtra - any additional elements needed -* cbMaxBufSize - optional argument for the maximum bytes allowed. Default is the maximum -* possible value for the architecture. -* -* Return: -* Either a mathematically correct number of bytes required, or in the case of an error, -* INVALID_BUFFER_SIZE -* -* Revision history: -* 10/22/04 - dleblanc - created -*/ + * MsoCbBufSizeT + * This function returns the bytes needed to allocate a buffer for (cElements + cExtra) + * instances of type T. This is a low level function, and typical usage would be to call + * one of the wrappers that deal with (for example) WCHAR arrays. + * + * Note: Strictly speaking, this isn't an exported MSO function, as it's instantiated by + * the caller, and simply picked up from the header. + * + * Arguments: + * cElements - the number of elements needed + * cExtra - any additional elements needed + * cbMaxBufSize - optional argument for the maximum bytes allowed. Default is the maximum + * possible value for the architecture. + * + * Return: + * Either a mathematically correct number of bytes required, or in the case of an error, + * INVALID_BUFFER_SIZE + * + * Revision history: + * 10/22/04 - dleblanc - created + */ const size_t INVALID_BUFFER_SIZE = ((size_t)~0); const size_t MAXIMUM_BUFFER_SIZE = ((size_t)INT_MAX); template -_Ret_range_(==, (cElements + cExtra) * sizeof(T)) -size_t MsoCbBufSizeT(size_t cElements, size_t cExtra = 0, size_t cbMaxBufSize = MAXIMUM_BUFFER_SIZE) noexcept +_Ret_range_(==, (cElements + cExtra) * sizeof(T)) size_t + MsoCbBufSizeT(size_t cElements, size_t cExtra = 0, size_t cbMaxBufSize = MAXIMUM_BUFFER_SIZE) noexcept { - //first calculate maximum allowed - //typical case is a compile time constant - const size_t cMax = cbMaxBufSize/sizeof(T); - const size_t cMaxAllowed = cMax - cExtra; + // first calculate maximum allowed + // typical case is a compile time constant + const size_t cMax = cbMaxBufSize / sizeof(T); + const size_t cMaxAllowed = cMax - cExtra; - if(cExtra > cMax || //cExtra is too large - cElements > cMaxAllowed) //real check here - { + if (cExtra > cMax || // cExtra is too large + cElements > cMaxAllowed) // real check here + { #if DEBUG - // TODO: This should be changed to a tagged function - //__asm int 3 + // TODO: This should be changed to a tagged function + //__asm int 3 #endif - //we have a problem - return INVALID_BUFFER_SIZE; - } + // we have a problem + return INVALID_BUFFER_SIZE; + } - return (cElements + cExtra) * sizeof(T); + return (cElements + cExtra) * sizeof(T); } /* -* MsoCbBufSizeExT -* -* Variant of MsoCbBufSizeT in which you may specify an additional "cbExtra" size -* (for array headers, etc.) -* -* Arguments: -* cElements - the number of elements needed -* cbExtra - any additional bytes needed -* cExtra - any additional elements needed -* cbMaxBufSize - optional argument for the maximum bytes allowed. Default is the maximum -* possible value for the architecture. -* -* Return: -* Either a mathematically correct number of bytes required, or in the case of an error, -* INVALID_BUFFER_SIZE -* -* Revision history: -* 8/14/05 - LeeHu - created -*/ + * MsoCbBufSizeExT + * + * Variant of MsoCbBufSizeT in which you may specify an additional "cbExtra" size + * (for array headers, etc.) + * + * Arguments: + * cElements - the number of elements needed + * cbExtra - any additional bytes needed + * cExtra - any additional elements needed + * cbMaxBufSize - optional argument for the maximum bytes allowed. Default is the maximum + * possible value for the architecture. + * + * Return: + * Either a mathematically correct number of bytes required, or in the case of an error, + * INVALID_BUFFER_SIZE + * + * Revision history: + * 8/14/05 - LeeHu - created + */ template -_Ret_range_(==, (cElements + cExtra) * sizeof(T) + cbExtra) -size_t MsoCbBufSizeExT(size_t cElements, size_t cbExtra, size_t cExtra = 0, size_t cbMaxBufSize = MAXIMUM_BUFFER_SIZE) noexcept +_Ret_range_(==, (cElements + cExtra) * sizeof(T) + cbExtra) size_t MsoCbBufSizeExT( + size_t cElements, + size_t cbExtra, + size_t cExtra = 0, + size_t cbMaxBufSize = MAXIMUM_BUFFER_SIZE) noexcept { - //first calculate maximum allowed - const size_t cbMax = cbMaxBufSize - cbExtra; - const size_t cMax = cbMax/sizeof(T); - const size_t cMaxAllowed = cMax - cExtra; + // first calculate maximum allowed + const size_t cbMax = cbMaxBufSize - cbExtra; + const size_t cMax = cbMax / sizeof(T); + const size_t cMaxAllowed = cMax - cExtra; - if(cbExtra > cbMaxBufSize || //cbExtra is too large - cExtra > cMax || //cExtra is too large - cElements > cMaxAllowed //"real" buf size check here - ) - { + if (cbExtra > cbMaxBufSize || // cbExtra is too large + cExtra > cMax || // cExtra is too large + cElements > cMaxAllowed //"real" buf size check here + ) + { #if DEBUG - // TODO: This should be changed to a tagged function - //__asm int 3 + // TODO: This should be changed to a tagged function + //__asm int 3 #endif - //we have a problem - return INVALID_BUFFER_SIZE; - } + // we have a problem + return INVALID_BUFFER_SIZE; + } - return (cElements + cExtra) * sizeof(T) + cbExtra; + return (cElements + cExtra) * sizeof(T) + cbExtra; } #endif // __cplusplus diff --git a/libs/memoryApi/src/crt/allocationSize.cpp b/libs/memoryApi/src/crt/allocationSize.cpp index 5bfb3a7..07a7e30 100644 --- a/libs/memoryApi/src/crt/allocationSize.cpp +++ b/libs/memoryApi/src/crt/allocationSize.cpp @@ -2,21 +2,17 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include -namespace Mso +namespace Mso { namespace Memory { +MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept { - namespace Memory - { - MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept - { - if (pv == nullptr) - return 0; + if (pv == nullptr) + return 0; - return ::_msize(const_cast(pv)); - } - } + return ::_msize(const_cast(pv)); } +}} // namespace Mso::Memory diff --git a/libs/memoryApi/src/crt/allocationSizeEmptyImpl.cpp b/libs/memoryApi/src/crt/allocationSizeEmptyImpl.cpp index 6d7311c..56f9f52 100644 --- a/libs/memoryApi/src/crt/allocationSizeEmptyImpl.cpp +++ b/libs/memoryApi/src/crt/allocationSizeEmptyImpl.cpp @@ -2,19 +2,15 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include -namespace Mso +namespace Mso { namespace Memory { +MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept { - namespace Memory - { - MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept - { - AssertSzTag(false, "AllocationSize is not implemented for this platform", 0x006951de /* tag_a0vh4 */); - return 0; - } - } + AssertSzTag(false, "AllocationSize is not implemented for this platform", 0x006951de /* tag_a0vh4 */); + return 0; } +}} // namespace Mso::Memory diff --git a/libs/memoryApi/src/crt/allocationSize_android.cpp b/libs/memoryApi/src/crt/allocationSize_android.cpp index d4fab45..1c4db39 100644 --- a/libs/memoryApi/src/crt/allocationSize_android.cpp +++ b/libs/memoryApi/src/crt/allocationSize_android.cpp @@ -2,18 +2,14 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include -namespace Mso +namespace Mso { namespace Memory { +MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept { - namespace Memory - { - MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept - { - return malloc_usable_size(pv); - } - } + return malloc_usable_size(pv); } +}} // namespace Mso::Memory diff --git a/libs/memoryApi/src/crt/allocationSize_apple.cpp b/libs/memoryApi/src/crt/allocationSize_apple.cpp index eeae509..96abc54 100644 --- a/libs/memoryApi/src/crt/allocationSize_apple.cpp +++ b/libs/memoryApi/src/crt/allocationSize_apple.cpp @@ -7,16 +7,12 @@ CRT based implementation for Mso::Memory on Apple platform #include #include -namespace Mso +namespace Mso { namespace Memory { +MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept { - namespace Memory - { - MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void* pv) noexcept - { - if (pv == nullptr) - return 0; + if (pv == nullptr) + return 0; - return ::malloc_size(const_cast(pv)); - } - } + return ::malloc_size(const_cast(pv)); } +}} // namespace Mso::Memory diff --git a/libs/memoryApi/src/crt/debugCheckHeap.cpp b/libs/memoryApi/src/crt/debugCheckHeap.cpp index 0c19791..16714d0 100644 --- a/libs/memoryApi/src/crt/debugCheckHeap.cpp +++ b/libs/memoryApi/src/crt/debugCheckHeap.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include @@ -12,8 +12,7 @@ MSOAPI_(BOOL) MsoCheckHeap(void) noexcept { - return ::_heapchk() == _HEAPOK; + return ::_heapchk() == _HEAPOK; } #endif // DEBUG - diff --git a/libs/memoryApi/src/crt/debugCheckHeapEmptyImpl.cpp b/libs/memoryApi/src/crt/debugCheckHeapEmptyImpl.cpp index 9b48281..6c61a39 100644 --- a/libs/memoryApi/src/crt/debugCheckHeapEmptyImpl.cpp +++ b/libs/memoryApi/src/crt/debugCheckHeapEmptyImpl.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include @@ -11,8 +11,8 @@ MSOAPI_(BOOL) MsoCheckHeap(void) noexcept { - AssertSzTag(false, "MsoCheckHeap is not implemented for this platform", 0x0125310c /* tag_bjtem */); - return true; + AssertSzTag(false, "MsoCheckHeap is not implemented for this platform", 0x0125310c /* tag_bjtem */); + return true; } #endif // DEBUG diff --git a/libs/memoryApi/src/crt/debugCheckHeap_android.cpp b/libs/memoryApi/src/crt/debugCheckHeap_android.cpp index e1eeb00..9202fd5 100644 --- a/libs/memoryApi/src/crt/debugCheckHeap_android.cpp +++ b/libs/memoryApi/src/crt/debugCheckHeap_android.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include @@ -11,8 +11,8 @@ MSOAPI_(BOOL) MsoCheckHeap(void) noexcept { - AssertSzTag(false, "MsoCheckHeap is not implemented for this platform", 0x027c404d /* tag_c5ebn */); - return true; + AssertSzTag(false, "MsoCheckHeap is not implemented for this platform", 0x027c404d /* tag_c5ebn */); + return true; } #endif // DEBUG diff --git a/libs/memoryApi/src/crt/debugCheckHeap_apple.cpp b/libs/memoryApi/src/crt/debugCheckHeap_apple.cpp index 83b8678..8d60877 100644 --- a/libs/memoryApi/src/crt/debugCheckHeap_apple.cpp +++ b/libs/memoryApi/src/crt/debugCheckHeap_apple.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include @@ -11,8 +11,8 @@ MSOAPI_(BOOL) MsoCheckHeap(void) noexcept { - // passing nullptr checks all zones - return malloc_zone_check(nullptr); + // passing nullptr checks all zones + return malloc_zone_check(nullptr); } #endif // DEBUG diff --git a/libs/memoryApi/src/crt/memoryApi.cpp b/libs/memoryApi/src/crt/memoryApi.cpp index a185ea7..2bac87b 100644 --- a/libs/memoryApi/src/crt/memoryApi.cpp +++ b/libs/memoryApi/src/crt/memoryApi.cpp @@ -2,87 +2,89 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include #include #if !__clang__ && !__GNUC__ - #pragma detect_mismatch("Allocator", "Crt") +#pragma detect_mismatch("Allocator", "Crt") #endif -__declspec(noreturn) void ThrowOOM() { throw std::bad_alloc(); } - -namespace Mso { namespace Memory { - -_Use_decl_annotations_ -void* AllocateEx(size_t cb, DWORD /*allocFlags*/) noexcept +__declspec(noreturn) void ThrowOOM() { - return ::malloc(cb); + throw std::bad_alloc(); } -_Use_decl_annotations_ -void* Reallocate(void** ppv, size_t cb) noexcept +namespace Mso { namespace Memory { + +_Use_decl_annotations_ void* AllocateEx(size_t cb, DWORD /*allocFlags*/) noexcept { - if (ppv == nullptr) - return Mso::Memory::Allocate(cb); - - if (*ppv == nullptr) - { - *ppv = Mso::Memory::Allocate(cb); - return *ppv; - } - - void* pv = ::realloc(*ppv, cb); - if (pv != nullptr) - { - *ppv = pv; - } - else if (cb == 0) - { - // HeapReAlloc with 0 size returns valid pointer and we want all implementations do the same - // realloc(ptr, 0) on Windows or Mac/iOS with ASAN frees the original pointer and returns null - // std lib on Mac/iOS returns a valid 0-sized pointer - // We want to standardize to have only one behavior in shared code - // so let's allocate a new 0-sized block if resize(ptr, 0) returns nullptr - pv = ::malloc(0); - *ppv = pv; - } - //else pv = nullptr, cb != 0: if realloc truly failed, the original ptr is untouched - - return pv; + return ::malloc(cb); } -_Use_decl_annotations_ -void Free(void* pv) noexcept +_Use_decl_annotations_ void* Reallocate(void** ppv, size_t cb) noexcept { - ::free(pv); + if (ppv == nullptr) + return Mso::Memory::Allocate(cb); + + if (*ppv == nullptr) + { + *ppv = Mso::Memory::Allocate(cb); + return *ppv; + } + + void* pv = ::realloc(*ppv, cb); + if (pv != nullptr) + { + *ppv = pv; + } + else if (cb == 0) + { + // HeapReAlloc with 0 size returns valid pointer and we want all implementations do the same + // realloc(ptr, 0) on Windows or Mac/iOS with ASAN frees the original pointer and returns null + // std lib on Mac/iOS returns a valid 0-sized pointer + // We want to standardize to have only one behavior in shared code + // so let's allocate a new 0-sized block if resize(ptr, 0) returns nullptr + pv = ::malloc(0); + *ppv = pv; + } + // else pv = nullptr, cb != 0: if realloc truly failed, the original ptr is untouched + + return pv; +} + +_Use_decl_annotations_ void Free(void* pv) noexcept +{ + ::free(pv); } #ifdef DEBUG void RegisterCallback(Mso::LibletAPI::ILibletMemoryMarking&) noexcept {} void UnregisterCallback(Mso::LibletAPI::ILibletMemoryMarking&) noexcept {} -#endif +#endif -}} // Mso::Memory +}} // namespace Mso::Memory #ifdef DEBUG -MSOAPI_(void) MsoSetLazyLeakDetection(const void *) noexcept +MSOAPI_(void) MsoSetLazyLeakDetection(const void*) noexcept {} + +MSOAPI_(void) MsoSetShutdownLeakDetection(const void*) noexcept {} + +MSOAPI_(BOOL) +FMemHeapMsoSaveBeHost( + void* /*pinst*/, + LPARAM /*lParam*/, + const void* /*pvBlock*/, + LONG_PTR /*cb*/, + struct IMsoMemHeap* /*pmmh*/) noexcept { + return true; } -MSOAPI_(void) MsoSetShutdownLeakDetection(const void *) noexcept -{ -} - -MSOAPI_(BOOL) FMemHeapMsoSaveBeHost(void* /*pinst*/, LPARAM /*lParam*/, const void* /*pvBlock*/, LONG_PTR /*cb*/, struct IMsoMemHeap* /*pmmh*/) noexcept -{ - return true; -} - -//MSOAPI_(VOID) MsoDebugRegisterLazyObject(IMsoDebugLazyObject* /*pidlo*/) noexcept {} -//MSOAPI_(VOID) MsoDebugUnregisterLazyObjectThreaded(IMsoDebugLazyObject* /*pidlo*/, bool /*fMainThread*/) noexcept {} +// MSOAPI_(VOID) MsoDebugRegisterLazyObject(IMsoDebugLazyObject* /*pidlo*/) noexcept {} +// MSOAPI_(VOID) MsoDebugUnregisterLazyObjectThreaded(IMsoDebugLazyObject* /*pidlo*/, bool /*fMainThread*/) noexcept {} #endif // DEBUG diff --git a/libs/memoryApi/src/emptyImpl/memoryApi.cpp b/libs/memoryApi/src/emptyImpl/memoryApi.cpp index d35e12e..95fdfe0 100644 --- a/libs/memoryApi/src/emptyImpl/memoryApi.cpp +++ b/libs/memoryApi/src/emptyImpl/memoryApi.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - CRT based implementation for Mso::Memory + CRT based implementation for Mso::Memory */ #include #include @@ -10,58 +10,73 @@ #pragma detect_mismatch("Allocator", "EmptyImpl") -__declspec(noreturn) void ThrowOOM() { throw std::bad_alloc(); } +__declspec(noreturn) void ThrowOOM() +{ + throw std::bad_alloc(); +} -namespace Mso { namespace Memory { +namespace Mso { namespace Memory { MSOCPPAPI_(size_t) AllocationSize(_In_opt_ const void*) noexcept { - VerifyElseCrashTag(false, 0x0115e605 /* tag_bf4yf */); + VerifyElseCrashTag(false, 0x0115e605 /* tag_bf4yf */); } MSOCPPAPI_(void*) AllocateEx(size_t /*cb*/, DWORD /*allocFlags*/) noexcept { - VerifyElseCrashTag(false, 0x006cc64b /* tag_a1mzl */); + VerifyElseCrashTag(false, 0x006cc64b /* tag_a1mzl */); } MSOCPPAPI_(void*) Reallocate(_Inout_ void** /*ppv*/, size_t /*cb*/) noexcept { - VerifyElseCrashTag(false, 0x006cc64c /* tag_a1mzm */); + VerifyElseCrashTag(false, 0x006cc64c /* tag_a1mzm */); } MSOCPPAPI_(void) Free(_In_opt_ void* /*pv*/) noexcept { - VerifyElseCrashTag(false, 0x006cc64d /* tag_a1mzn */); + VerifyElseCrashTag(false, 0x006cc64d /* tag_a1mzn */); } #ifdef DEBUG -MSOCPPAPI_(void) RegisterCallback(Mso::LibletAPI::ILibletMemoryMarking&) noexcept { VerifyElseCrashTag(false, 0x006cc64e /* tag_a1mzo */); } -MSOCPPAPI_(void) UnregisterCallback(Mso::LibletAPI::ILibletMemoryMarking&) noexcept { VerifyElseCrashTag(false, 0x006cc64f /* tag_a1mzp */); } -#endif +MSOCPPAPI_(void) RegisterCallback(Mso::LibletAPI::ILibletMemoryMarking&) noexcept +{ + VerifyElseCrashTag(false, 0x006cc64e /* tag_a1mzo */); +} +MSOCPPAPI_(void) UnregisterCallback(Mso::LibletAPI::ILibletMemoryMarking&) noexcept +{ + VerifyElseCrashTag(false, 0x006cc64f /* tag_a1mzp */); +} +#endif -}} // Mso::Memory +}} // namespace Mso::Memory #ifdef DEBUG MSOAPI_(BOOL) MsoCheckHeap(void) noexcept { - VerifyElseCrashTag(false, 0x0125310d /* tag_bjten */); - return true; + VerifyElseCrashTag(false, 0x0125310d /* tag_bjten */); + return true; } -MSOAPI_(void) MsoSetLazyLeakDetection(const void *) noexcept +MSOAPI_(void) MsoSetLazyLeakDetection(const void*) noexcept { - VerifyElseCrashTag(false, 0x006cc650 /* tag_a1mzq */); + VerifyElseCrashTag(false, 0x006cc650 /* tag_a1mzq */); } -MSOAPI_(void) MsoSetShutdownLeakDetection(const void *) noexcept +MSOAPI_(void) MsoSetShutdownLeakDetection(const void*) noexcept { - VerifyElseCrashTag(false, 0x006cc651 /* tag_a1mzr */); + VerifyElseCrashTag(false, 0x006cc651 /* tag_a1mzr */); } -MSOAPI_(BOOL) FMemHeapMsoSaveBeHost(void* /*pinst*/, LPARAM /*lParam*/, const void* /*pvBlock*/, LONG_PTR /*cb*/, struct IMsoMemHeap* /*pmmh*/) noexcept +MSOAPI_(BOOL) +FMemHeapMsoSaveBeHost( + void* /*pinst*/, + LPARAM /*lParam*/, + const void* /*pvBlock*/, + LONG_PTR /*cb*/, + struct IMsoMemHeap* /*pmmh*/) noexcept { - VerifyElseCrashTag(false, 0x006cc652 /* tag_a1mzs */); + VerifyElseCrashTag(false, 0x006cc652 /* tag_a1mzs */); } MSOAPI_(VOID) MsoDebugRegisterLazyObject(IMsoDebugLazyObject* /*pidlo*/) noexcept {} diff --git a/libs/memoryApi/src/emptyImpl/memoryLeakScope_EmptyImpl.cpp b/libs/memoryApi/src/emptyImpl/memoryLeakScope_EmptyImpl.cpp index 413b79a..57c2c4e 100644 --- a/libs/memoryApi/src/emptyImpl/memoryLeakScope_EmptyImpl.cpp +++ b/libs/memoryApi/src/emptyImpl/memoryLeakScope_EmptyImpl.cpp @@ -2,46 +2,35 @@ // Licensed under the MIT license. /** - Empty implementation for memoryleakscope + Empty implementation for memoryleakscope - DO NOT INCLUDE THIS HEADER - LINK WITH THE LOB - (unless you need to link in pass0 e.g. msoprep\legacy) + DO NOT INCLUDE THIS HEADER - LINK WITH THE LOB + (unless you need to link in pass0 e.g. msoprep\legacy) */ #include #ifdef DEBUG -namespace Mso { -namespace Memory { +namespace Mso { namespace Memory { bool IsInShutdownLeakScope() noexcept { - return false; + return false; } -void EnterShutdownLeakScope(unsigned int /*framesToSkip*/) noexcept -{ -} +void EnterShutdownLeakScope(unsigned int /*framesToSkip*/) noexcept {} -void LeaveShutdownLeakScope() noexcept -{ -} +void LeaveShutdownLeakScope() noexcept {} bool IsInIgnoreLeakScope() noexcept { - return false; + return false; } -void EnterIgnoreLeakScope(unsigned int /*framesToSkip*/) noexcept -{ -} +void EnterIgnoreLeakScope(unsigned int /*framesToSkip*/) noexcept {} -void LeaveIgnoreLeakScope() noexcept -{ -} +void LeaveIgnoreLeakScope() noexcept {} -} // Memory -} // Mso +}} // namespace Mso::Memory #endif // DEBUG - diff --git a/libs/motifCpp/include/motifCpp/XCTestAdapter.h b/libs/motifCpp/include/motifCpp/XCTestAdapter.h index 048847f..fd2aca6 100644 --- a/libs/motifCpp/include/motifCpp/XCTestAdapter.h +++ b/libs/motifCpp/include/motifCpp/XCTestAdapter.h @@ -1,3 +1,2 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. - diff --git a/libs/motifCpp/include/motifCpp/assert_IgnorePlat_apple.h b/libs/motifCpp/include/motifCpp/assert_IgnorePlat_apple.h index a5948fc..386099d 100644 --- a/libs/motifCpp/include/motifCpp/assert_IgnorePlat_apple.h +++ b/libs/motifCpp/include/motifCpp/assert_IgnorePlat_apple.h @@ -18,72 +18,71 @@ // UNTAGGED that can conflict with tagutils.h. extern "C" { - typedef UInt32 nl_assert_tag_t; - - Boolean NLFAssertsEnabled(); - void NLEnableAllAsserts(Boolean inEnabled); + typedef UInt32 nl_assert_tag_t; - Boolean NLIsAssertEnabledByTag(nl_assert_tag_t inTag); - void NLDisableAssertByTag(nl_assert_tag_t inTag); - void NLEnableAssertByTag(nl_assert_tag_t inTag); + Boolean NLFAssertsEnabled(); + void NLEnableAllAsserts(Boolean inEnabled); + + Boolean NLIsAssertEnabledByTag(nl_assert_tag_t inTag); + void NLDisableAssertByTag(nl_assert_tag_t inTag); + void NLEnableAssertByTag(nl_assert_tag_t inTag); } #endif namespace Mso { #if DEBUG - class IgnoreAllAssertsPlatformImpl +class IgnoreAllAssertsPlatformImpl +{ +public: + IgnoreAllAssertsPlatformImpl() : m_nlEnabled(NLFAssertsEnabled()) + { + NLEnableAllAsserts(false); + } + + ~IgnoreAllAssertsPlatformImpl() + { + NLEnableAllAsserts(m_nlEnabled); + } + +private: + const bool m_nlEnabled; +}; + +class IgnoreAssertPlatformImpl +{ +public: + IgnoreAssertPlatformImpl(DWORD tag) : m_tag(tag), m_tagEnabled(NLIsAssertEnabledByTag(tag)) + { + if (m_tagEnabled) { - public: - IgnoreAllAssertsPlatformImpl() : - m_nlEnabled(NLFAssertsEnabled()) - { - NLEnableAllAsserts(false); - } - - ~IgnoreAllAssertsPlatformImpl() - { - NLEnableAllAsserts(m_nlEnabled); - } - - private: - const bool m_nlEnabled; - }; - - class IgnoreAssertPlatformImpl + NLDisableAssertByTag(m_tag); + } + } + + ~IgnoreAssertPlatformImpl() + { + if (m_tagEnabled) { - public: - IgnoreAssertPlatformImpl(DWORD tag) : - m_tag(tag), - m_tagEnabled(NLIsAssertEnabledByTag(tag)) - { - if (m_tagEnabled) - { - NLDisableAssertByTag(m_tag); - } - } - - ~IgnoreAssertPlatformImpl() - { - if (m_tagEnabled) - { - NLEnableAssertByTag(m_tag); - } - } - - private: - const bool m_tagEnabled; - const nl_assert_tag_t m_tag; - }; + NLEnableAssertByTag(m_tag); + } + } + +private: + const bool m_tagEnabled; + const nl_assert_tag_t m_tag; +}; #else // DEBUG - class IgnoreAllAssertsPlatformImpl {}; - class IgnoreAssertPlatformImpl - { - public: - IgnoreAssertPlatformImpl(uint32_t) {} - }; +class IgnoreAllAssertsPlatformImpl +{ +}; +class IgnoreAssertPlatformImpl +{ +public: + IgnoreAssertPlatformImpl(uint32_t) {} +}; #endif - -} // Mso + +} // namespace Mso #endif // MOTIFCPP_ASSERT_IGNOREPLAT_APPLE_H diff --git a/libs/motifCpp/include/motifCpp/assert_IgnorePlat_emptyImpl.h b/libs/motifCpp/include/motifCpp/assert_IgnorePlat_emptyImpl.h index 5f414bf..14c2aa6 100644 --- a/libs/motifCpp/include/motifCpp/assert_IgnorePlat_emptyImpl.h +++ b/libs/motifCpp/include/motifCpp/assert_IgnorePlat_emptyImpl.h @@ -12,14 +12,16 @@ namespace Mso { - class IgnoreAllAssertsPlatformImpl {}; +class IgnoreAllAssertsPlatformImpl +{ +}; - class IgnoreAssertPlatformImpl - { - public: - IgnoreAssertPlatformImpl(uint32_t) {} - }; +class IgnoreAssertPlatformImpl +{ +public: + IgnoreAssertPlatformImpl(uint32_t) {} +}; -} // Mso +} // namespace Mso #endif // MOTIFCPP_ASSERT_IGNOREPLAT_EMPTYIMPL_H diff --git a/libs/motifCpp/include/motifCpp/assert_motifApi.h b/libs/motifCpp/include/motifCpp/assert_motifApi.h index 1bc4957..45a9e22 100644 --- a/libs/motifCpp/include/motifCpp/assert_motifApi.h +++ b/libs/motifCpp/include/motifCpp/assert_motifApi.h @@ -6,10 +6,10 @@ #define MOTIFCPP_ASSERT_MOTIFAPI_H #include "motifCppTest.h" -#define BeginSupportFileMap() \ +#define BeginSupportFileMap() -#define Dependency(filepath) \ +#define Dependency(filepath) -#define EndSupportFileMap() \ +#define EndSupportFileMap() #endif // MOTIFCPP_ASSERT_MOTIFAPI_H \ No newline at end of file diff --git a/libs/motifCpp/include/motifCpp/gTestAdapter.h b/libs/motifCpp/include/motifCpp/gTestAdapter.h index 3d823d8..f0e0c88 100644 --- a/libs/motifCpp/include/motifCpp/gTestAdapter.h +++ b/libs/motifCpp/include/motifCpp/gTestAdapter.h @@ -14,8 +14,7 @@ namespace Mso { namespace UnitTests { namespace GTest { struct GTestFixture : ::testing::Test { explicit GTestFixture(const TestClassInfo& classInfo, const TestMethodInfo& methodInfo) - : m_methodInfo { methodInfo } - , m_test { classInfo.CreateTest() } + : m_methodInfo{methodInfo}, m_test{classInfo.CreateTest()} { } @@ -24,26 +23,18 @@ struct GTestFixture : ::testing::Test m_methodInfo.Invoke(*m_test); } - static void SetUpTestSuite() - { - } + static void SetUpTestSuite() {} - static void TearDownTestSuite() - { - } + static void TearDownTestSuite() {} - void SetUp() override - { - } + void SetUp() override {} - void TearDown() override - { - } + void TearDown() override {} - private: - const TestMethodInfo& m_methodInfo; - std::unique_ptr m_test; - }; +private: + const TestMethodInfo& m_methodInfo; + std::unique_ptr m_test; +}; inline void RegisterUnitTests() { @@ -52,13 +43,15 @@ inline void RegisterUnitTests() for (const TestMethodInfo* methodInfo : classInfo->MethodInfos()) { ::testing::RegisterTest( - /*test_suite_name:*/classInfo->ClassName(), - /*test_name:*/methodInfo->MethodName(), - /*type_param:*/nullptr, - /*value_param:*/nullptr, - /*file:*/classInfo->FileName(), - /*line:*/methodInfo->SourceLine(), - /*factory:*/[classInfo, methodInfo]() { return new GTestFixture { *classInfo, *methodInfo }; }); + /*test_suite_name:*/ classInfo->ClassName(), + /*test_name:*/ methodInfo->MethodName(), + /*type_param:*/ nullptr, + /*value_param:*/ nullptr, + /*file:*/ classInfo->FileName(), + /*line:*/ methodInfo->SourceLine(), + /*factory:*/ [classInfo, methodInfo]() { + return new GTestFixture{*classInfo, *methodInfo}; + }); } } } diff --git a/libs/motifCpp/include/motifCpp/motifCppTest.h b/libs/motifCpp/include/motifCpp/motifCppTest.h index a8447de..c827e66 100644 --- a/libs/motifCpp/include/motifCpp/motifCppTest.h +++ b/libs/motifCpp/include/motifCpp/motifCppTest.h @@ -11,11 +11,11 @@ #include #if defined(MSO_USE_GTEST) -# include +#include #elif defined(MSO_USE_XCTEST) -# include +#include #else -# error "Undefined unit test framework" +#error "Undefined unit test framework" #endif typedef wchar_t WCHAR; @@ -25,175 +25,186 @@ namespace TestAssert { // Asserts that the specified condition is true, if it is false the unit test will fail inline void IsTrue(bool condition, _In_z_ const WCHAR* message = L"") { - ASSERT_TRUE(condition) << message; + ASSERT_TRUE(condition) << message; } // Verify that a condition is true: -template::value>::type> +template ::value>::type> inline void IsTrue(const T& condition, _In_z_ const WCHAR* message = L"") { - return IsTrue(!!condition, message); + return IsTrue(!!condition, message); } // Asserts that the specified condition is false, if it is true the unit test will fail inline void IsFalse(bool condition, const WCHAR* message = L"") { - ASSERT_FALSE(condition) << message; + ASSERT_FALSE(condition) << message; } -template::value>::type> +template ::value>::type> inline void IsFalse(const T& condition, _In_z_ const WCHAR* message = L"") { - return IsFalse(!!condition, message); + return IsFalse(!!condition, message); } template -inline void AreEqual(_In_ const ExpectedType& expected, _In_ const ActualType& actual, _In_z_ const WCHAR* message = L"") +inline void +AreEqual(_In_ const ExpectedType& expected, _In_ const ActualType& actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_EQ(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_EQ(expected, actual) << wstrMessage.c_str(); } -template ::value - && !std::is_same::value && !std::is_same::value>::type> +template < + typename ExpectedType, + typename ActualType, + typename TEnable = typename std::enable_if< + std::is_same::value && !std::is_same::value + && !std::is_same::value>::type> void AreEqual(_In_ const ExpectedType* expected, _In_ const ActualType* actual, _In_z_ const WCHAR* message = L"") { - AreEqual(*expected, *actual, message); + AreEqual(*expected, *actual, message); } inline void AreEqual(_In_ const wchar_t* expected, _In_ const wchar_t* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); } inline void AreEqual(_In_ const char* expected, _In_ const char* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); } inline void AreEqual(_In_ wchar_t* expected, _In_ const wchar_t* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); } inline void AreEqual(_In_ char* expected, _In_ const char* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STREQ(expected, actual) << wstrMessage.c_str(); } template -inline void AreNotEqual(_In_ const ExpectedType& expected, _In_ const ActualType& actual, _In_z_ const WCHAR* message = L"") +inline void +AreNotEqual(_In_ const ExpectedType& expected, _In_ const ActualType& actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_NE(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_NE(expected, actual) << wstrMessage.c_str(); } -template ::value - && !std::is_same::value && !std::is_same::value>::type> +template < + typename ExpectedType, + typename ActualType, + typename TEnable = typename std::enable_if< + std::is_same::value && !std::is_same::value + && !std::is_same::value>::type> void AreNotEqual(_In_ const ExpectedType* expected, _In_ const ActualType* actual, _In_z_ const WCHAR* message = L"") { - AreNotEqual(*expected, *actual, message); + AreNotEqual(*expected, *actual, message); } inline void AreNotEqual(_In_ const wchar_t* expected, _In_ const wchar_t* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); } inline void AreNotEqual(_In_ const char* expected, _In_ const char* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); } inline void AreNotEqual(_In_ wchar_t* expected, _In_ const wchar_t* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); } inline void AreNotEqual(_In_ char* expected, _In_ const char* actual, _In_z_ const WCHAR* message = L"") { - std::wstring wstrMessage(message); - ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); + std::wstring wstrMessage(message); + ASSERT_STRNE(expected, actual) << wstrMessage.c_str(); } inline void Comment(_In_ const WCHAR* message) { - std::wcerr << L"[ INFO ] " << message << std::endl; + std::wcerr << L"[ INFO ] " << message << std::endl; } inline void CommentEx(_In_z_ _Printf_format_string_ const WCHAR* format, va_list args) noexcept { - fwprintf(stderr, L"[ INFO ] "); - vfwprintf(stderr, format, args); - fwprintf(stderr, L"\n"); + fwprintf(stderr, L"[ INFO ] "); + vfwprintf(stderr, format, args); + fwprintf(stderr, L"\n"); } inline void CommentEx(_In_z_ _Printf_format_string_ const WCHAR* format, ...) noexcept { - va_list args; - va_start(args, format); - fwprintf(stderr, L"[ INFO ] "); - vfwprintf(stderr, format, args); - va_end(args); - fwprintf(stderr, L"\n"); + va_list args; + va_start(args, format); + fwprintf(stderr, L"[ INFO ] "); + vfwprintf(stderr, format, args); + va_end(args); + fwprintf(stderr, L"\n"); } inline void Pass(_In_z_ const WCHAR* message = L"") noexcept { - ASSERT_TRUE(true) << message; + ASSERT_TRUE(true) << message; } inline void Fail(_In_z_ const WCHAR* message = L"") { - ASSERT_TRUE(false) << message; + ASSERT_TRUE(false) << message; } -template +template inline void IsNull(const ValueType& ptr, _In_z_ const WCHAR* message = L"") { - AreEqual(ptr, nullptr, message); + AreEqual(ptr, nullptr, message); } -template +template inline void IsNotNull(const ValueType& ptr, _In_z_ const WCHAR* message = L"") { - AreNotEqual(ptr, nullptr, message); + AreNotEqual(ptr, nullptr, message); } -template -inline void ExpectException(const std::function& statement, const WCHAR* message = L"") +template +inline void ExpectException(const std::function& statement, const WCHAR* message = L"") { - EXPECT_THROW(statement(), ExceptionType) << message; + EXPECT_THROW(statement(), ExceptionType) << message; } -template -inline void ExpectException(const std::function& statement, const std::function& onException, const WCHAR* message = L"") +template +inline void ExpectException( + const std::function& statement, + const std::function& onException, + const WCHAR* message = L"") { - EXPECT_THROW(statement(), ExceptionType) << message; + EXPECT_THROW(statement(), ExceptionType) << message; } -inline void ExpectNoThrow(const std::function& statement, const WCHAR* message = L"") +inline void ExpectNoThrow(const std::function& statement, const WCHAR* message = L"") { - EXPECT_NO_THROW(statement()) << message; + EXPECT_NO_THROW(statement()) << message; } inline void HrSucceeded(HRESULT hr, _In_z_ const WCHAR* message = L"") { - ASSERT_TRUE(SUCCEEDED(hr)) << message; + ASSERT_TRUE(SUCCEEDED(hr)) << message; } inline void HrFailed(HRESULT hr, _In_z_ const WCHAR* message = L"") { - ASSERT_FALSE(SUCCEEDED(hr)) << message; + ASSERT_FALSE(SUCCEEDED(hr)) << message; } #ifdef MS_TARGET_WINDOWS @@ -202,35 +213,35 @@ static const DWORD EXCEPTION_CPLUSPLUS = static_cast(0xE06D7363); inline DWORD FilterCrashExceptions(DWORD exceptionCode) noexcept { - if ((exceptionCode == EXCEPTION_BREAKPOINT) // allow exceptions to get to the debugger - || (exceptionCode == EXCEPTION_SINGLE_STEP) // allow exceptions to get to the debugger - || (exceptionCode == EXCEPTION_GUARD_PAGE) // allow to crash on memory page access violation - || (exceptionCode == EXCEPTION_STACK_OVERFLOW)) // allow to crash on stack overflow - { - return EXCEPTION_CONTINUE_SEARCH; - } - if (exceptionCode == EXCEPTION_CPLUSPLUS) // log C++ exception and pass it through - { - TestAssert::Fail(L"Test function did not crash, but exception is thrown!"); - return EXCEPTION_CONTINUE_SEARCH; - } - return EXCEPTION_EXECUTE_HANDLER; + if ((exceptionCode == EXCEPTION_BREAKPOINT) // allow exceptions to get to the debugger + || (exceptionCode == EXCEPTION_SINGLE_STEP) // allow exceptions to get to the debugger + || (exceptionCode == EXCEPTION_GUARD_PAGE) // allow to crash on memory page access violation + || (exceptionCode == EXCEPTION_STACK_OVERFLOW)) // allow to crash on stack overflow + { + return EXCEPTION_CONTINUE_SEARCH; + } + if (exceptionCode == EXCEPTION_CPLUSPLUS) // log C++ exception and pass it through + { + TestAssert::Fail(L"Test function did not crash, but exception is thrown!"); + return EXCEPTION_CONTINUE_SEARCH; + } + return EXCEPTION_EXECUTE_HANDLER; } -template +template inline bool ExpectCrashCore(const Fn& fn, const WCHAR* message) { - __try - { - fn(); - } - __except (FilterCrashExceptions(GetExceptionCode())) - { - //Pass(message == nullptr || message[0] == L'\0' ? L"Crash occurred as expected." : message); - return true; - } - //Fail(message == nullptr || message[0] == L'\0' ? L"Test function did not crash!" : message); - return false; + __try + { + fn(); + } + __except (FilterCrashExceptions(GetExceptionCode())) + { + // Pass(message == nullptr || message[0] == L'\0' ? L"Crash occurred as expected." : message); + return true; + } + // Fail(message == nullptr || message[0] == L'\0' ? L"Test function did not crash!" : message); + return false; } #else @@ -240,49 +251,48 @@ using SigAction = void (*)(int, siginfo_t*, void*); // restores the old one in the destructor. struct CrashState { - CrashState(SigAction action) noexcept - { - sigemptyset(&m_action.sa_mask); - m_action.sa_sigaction = action; - m_action.sa_flags = SA_NODEFER; - sigaction(SIGSEGV, &m_action, &m_oldAction); - } + CrashState(SigAction action) noexcept + { + sigemptyset(&m_action.sa_mask); + m_action.sa_sigaction = action; + m_action.sa_flags = SA_NODEFER; + sigaction(SIGSEGV, &m_action, &m_oldAction); + } - ~CrashState() noexcept - { - sigaction(SIGSEGV, &m_oldAction, nullptr); - } + ~CrashState() noexcept + { + sigaction(SIGSEGV, &m_oldAction, nullptr); + } private: - struct sigaction m_action{}; - struct sigaction m_oldAction{}; + struct sigaction m_action + { + }; + struct sigaction m_oldAction + { + }; }; // Returns true if crash (segmentation fault happened) template inline bool ExpectCrashCore(const Fn& fn, const WCHAR* message) { - static sigjmp_buf buf{}; + static sigjmp_buf buf{}; - // Set sigaction and save the previous action to be restored in the end of - // function. - CrashState crashState{ - [](int signal, siginfo_t *si, void *arg) - { - longjmp(buf, 1); - } - }; + // Set sigaction and save the previous action to be restored in the end of + // function. + CrashState crashState{[](int signal, siginfo_t* si, void* arg) { longjmp(buf, 1); }}; - // setjmp originally returns 0, and when longjmp is called it returns 1. - if (!setjmp(buf)) - { - fn(); - return true; // must not be executed if fn() caused crash and the longjmp is executed. - } - else - { - return true; // executed if longjmp is executed in the SigAction handler. - } + // setjmp originally returns 0, and when longjmp is called it returns 1. + if (!setjmp(buf)) + { + fn(); + return true; // must not be executed if fn() caused crash and the longjmp is executed. + } + else + { + return true; // executed if longjmp is executed in the SigAction handler. + } } #endif @@ -290,10 +300,10 @@ inline bool ExpectCrashCore(const Fn& fn, const WCHAR* message) template inline void ExpectVEC(const Fn& fn, const WCHAR* message = L"") { - if (!ExpectCrashCore(fn, message)) - { - Fail(message); - } + if (!ExpectCrashCore(fn, message)) + { + Fail(message); + } } -} // namespace TestAssert \ No newline at end of file +} // namespace TestAssert \ No newline at end of file diff --git a/libs/motifCpp/include/motifCpp/motifCppTestBase.h b/libs/motifCpp/include/motifCpp/motifCppTestBase.h index f636f0a..aa8e1b0 100644 --- a/libs/motifCpp/include/motifCpp/motifCppTestBase.h +++ b/libs/motifCpp/include/motifCpp/motifCppTestBase.h @@ -8,19 +8,18 @@ typedef wchar_t WCHAR; class MotifCppTestBase { public: - MotifCppTestBase() - {} + MotifCppTestBase() {} - ~MotifCppTestBase() - { - TestClassTeardown(); - } + ~MotifCppTestBase() + { + TestClassTeardown(); + } - virtual void TestClassSetup() {} + virtual void TestClassSetup() {} - virtual void TestClassTeardown() {} + virtual void TestClassTeardown() {} - virtual void Setup() {} + virtual void Setup() {} - virtual void Teardown() {} + virtual void Teardown() {} }; \ No newline at end of file diff --git a/libs/motifCpp/include/motifCpp/testInfo.h b/libs/motifCpp/include/motifCpp/testInfo.h index 928a665..129ca4a 100644 --- a/libs/motifCpp/include/motifCpp/testInfo.h +++ b/libs/motifCpp/include/motifCpp/testInfo.h @@ -10,37 +10,33 @@ #include #include -#define TEST_CLASS(className) \ - struct className; \ - \ - struct TestClassInfo_##className final \ - : Mso::UnitTests::Internal::TestClassInfoReg \ - { \ - TestClassInfo_##className() noexcept \ - : TestClassInfoRegType{ #className, __FILE__, __LINE__ } {} \ - };\ - \ - struct className : Mso::UnitTests::Internal::TestClassBase +#define TEST_CLASS(className) \ + struct className; \ + \ + struct TestClassInfo_##className final \ + : Mso::UnitTests::Internal::TestClassInfoReg \ + { \ + TestClassInfo_##className() noexcept : TestClassInfoRegType{#className, __FILE__, __LINE__} {} \ + }; \ + \ + struct className : Mso::UnitTests::Internal::TestClassBase -#define TEST_METHOD(methodName) \ - struct TestMethodInfo_##methodName final \ - : Mso::UnitTests::Internal::TestMethodInfoReg \ - { \ - TestMethodInfo_##methodName() \ - : TestMethodInfoRegType{ TestClassInfoType::Instance, #methodName, __LINE__ } {} \ - \ - void Invoke(Mso::UnitTests::TestClass& test) const override \ - { \ - static_cast(test).methodName(); \ - } \ - }; \ - virtual void methodName() +#define TEST_METHOD(methodName) \ + struct TestMethodInfo_##methodName final : Mso::UnitTests::Internal::TestMethodInfoReg \ + { \ + TestMethodInfo_##methodName() : TestMethodInfoRegType{TestClassInfoType::Instance, #methodName, __LINE__} {} \ + \ + void Invoke(Mso::UnitTests::TestClass& test) const override \ + { \ + static_cast(test).methodName(); \ + } \ + }; \ + virtual void methodName() #define TestClassComponent(x1, x2) // Allows a test to be compiled, but not executed -#define SKIPTESTMETHOD(methodName) \ - virtual void skipped_##methodName() +#define SKIPTESTMETHOD(methodName) virtual void skipped_##methodName() namespace Mso { namespace UnitTests { @@ -51,7 +47,7 @@ struct TestMethodInfo; template struct TestClassInfos { - static std::vector s_classInfos; + static std::vector s_classInfos; }; template @@ -59,56 +55,76 @@ std::vector TestClassInfos::s_classInfos; struct TestClassInfo { - TestClassInfo(const char* className, const char* fileName, int sourceLine) noexcept - : m_className { className } - , m_fileName { fileName } - , m_sourceLine { sourceLine } - { - TestClassInfos::s_classInfos.push_back(this); - } + TestClassInfo(const char* className, const char* fileName, int sourceLine) noexcept + : m_className{className}, m_fileName{fileName}, m_sourceLine{sourceLine} + { + TestClassInfos::s_classInfos.push_back(this); + } - const char* ClassName() const noexcept { return m_className; } - const char* FileName() const noexcept { return m_fileName; } - int SourceLine() const noexcept { return m_sourceLine; } - const std::vector& MethodInfos() const noexcept { return m_methodInfos; } - static const std::vector& ClassInfos() noexcept { return TestClassInfos::s_classInfos; } + const char* ClassName() const noexcept + { + return m_className; + } + const char* FileName() const noexcept + { + return m_fileName; + } + int SourceLine() const noexcept + { + return m_sourceLine; + } + const std::vector& MethodInfos() const noexcept + { + return m_methodInfos; + } + static const std::vector& ClassInfos() noexcept + { + return TestClassInfos::s_classInfos; + } - void AddMethodInfo(TestMethodInfo& methodInfo) noexcept - { - m_methodInfos.push_back(&methodInfo); - } + void AddMethodInfo(TestMethodInfo& methodInfo) noexcept + { + m_methodInfos.push_back(&methodInfo); + } public: // To implement in derived classes - virtual std::unique_ptr CreateTest() const = 0; + virtual std::unique_ptr CreateTest() const = 0; private: - const char* m_className { nullptr }; - const char* m_fileName { nullptr }; - int m_sourceLine { 0 }; - std::vector m_methodInfos; + const char* m_className{nullptr}; + const char* m_fileName{nullptr}; + int m_sourceLine{0}; + std::vector m_methodInfos; }; struct TestMethodInfo { - TestMethodInfo(TestClassInfo& classInfo, const char* methodName, int sourceLine) noexcept - : m_classInfo { classInfo } - , m_methodName { methodName } - , m_sourceLine { sourceLine } - { - classInfo.AddMethodInfo(*this); - } + TestMethodInfo(TestClassInfo& classInfo, const char* methodName, int sourceLine) noexcept + : m_classInfo{classInfo}, m_methodName{methodName}, m_sourceLine{sourceLine} + { + classInfo.AddMethodInfo(*this); + } - const TestClassInfo& ClassInfo() const noexcept { return m_classInfo; } - const char* MethodName() const noexcept { return m_methodName; } - int SourceLine() const noexcept { return m_sourceLine; } + const TestClassInfo& ClassInfo() const noexcept + { + return m_classInfo; + } + const char* MethodName() const noexcept + { + return m_methodName; + } + int SourceLine() const noexcept + { + return m_sourceLine; + } public: // To implement in derived classes - virtual void Invoke(TestClass& test) const = 0; + virtual void Invoke(TestClass& test) const = 0; private: - const TestClassInfo& m_classInfo; - const char* m_methodName { nullptr }; - int m_sourceLine { 0 }; + const TestClassInfo& m_classInfo; + const char* m_methodName{nullptr}; + int m_sourceLine{0}; }; }} // namespace Mso::UnitTests @@ -125,15 +141,15 @@ struct TestClassBase : TestClass template struct TestClassInfoReg : TestClassInfo { - using TestClassInfoRegType = TestClassInfoReg; - using TestClassInfo::TestClassInfo; + using TestClassInfoRegType = TestClassInfoReg; + using TestClassInfo::TestClassInfo; - static TClassInfo Instance; + static TClassInfo Instance; - std::unique_ptr CreateTest() const override - { - return std::unique_ptr { new TTestClass() }; - } + std::unique_ptr CreateTest() const override + { + return std::unique_ptr{new TTestClass()}; + } }; template @@ -142,15 +158,15 @@ TClassInfo TestClassInfoReg::Instance; template struct TestMethodInfoReg : TestMethodInfo { - using TestMethodInfoRegType = TestMethodInfoReg; + using TestMethodInfoRegType = TestMethodInfoReg; - TestMethodInfoReg(TestClassInfo& classInfo, const char* methodName, int sourceLine) noexcept - : TestMethodInfo { classInfo, methodName, sourceLine } - { - (void)&Instance; // To ensure that we create static instance - } + TestMethodInfoReg(TestClassInfo& classInfo, const char* methodName, int sourceLine) noexcept + : TestMethodInfo{classInfo, methodName, sourceLine} + { + (void)&Instance; // To ensure that we create static instance + } - static TMethodInfo Instance; + static TMethodInfo Instance; }; template diff --git a/libs/motifCpp/include/test/libletAwareMemLeakDetection.h b/libs/motifCpp/include/test/libletAwareMemLeakDetection.h index 082a30e..e837aaf 100644 --- a/libs/motifCpp/include/test/libletAwareMemLeakDetection.h +++ b/libs/motifCpp/include/test/libletAwareMemLeakDetection.h @@ -7,9 +7,7 @@ class LibletAwareMemLeakDetection : public MotifCppTestBase { protected: - void InitLiblets() noexcept - {} + void InitLiblets() noexcept {} - void UninitLiblets() noexcept - {} + void UninitLiblets() noexcept {} }; diff --git a/libs/motifCpp/include/test/skipSEHUT.h b/libs/motifCpp/include/test/skipSEHUT.h index 3643abb..373e8e1 100644 --- a/libs/motifCpp/include/test/skipSEHUT.h +++ b/libs/motifCpp/include/test/skipSEHUT.h @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -// This file is added temporary for the purpose of excluding the liblet UT's that used SEH. // +// This file is added temporary for the purpose of excluding the liblet UT's that used SEH. // // Currently there is no support for filtering in Android. Bug # OM: 1706117 Need Filter support for Android Unit tests. // // // Action item post this bug will be fixed ... -// we need to remove this file and all the occurrences of the macro TESTMETHOD_REQUIRES_SEH should be +// we need to remove this file and all the occurrences of the macro TESTMETHOD_REQUIRES_SEH should be // replaced with TESTMETHODEX(${1}, TestCategory(RequriesSEH)). #pragma once diff --git a/libs/motifCpp/include/test/testCheck.h b/libs/motifCpp/include/test/testCheck.h index 576993a..f1a42e0 100644 --- a/libs/motifCpp/include/test/testCheck.h +++ b/libs/motifCpp/include/test/testCheck.h @@ -24,46 +24,41 @@ // A helper macro to provide current line number as a wide char string. //============================================================================= #ifndef MSO_TO_STR -# define MSO_INTERNAL_TO_STR(value) #value -# define MSO_TO_STR(value) MSO_INTERNAL_TO_STR(value) +#define MSO_INTERNAL_TO_STR(value) #value +#define MSO_TO_STR(value) MSO_INTERNAL_TO_STR(value) #endif #ifndef MSO_WIDE_STR -# define MSO_INTERNAL_WIDE_STR(str) L ## str -# define MSO_WIDE_STR(str) MSO_INTERNAL_WIDE_STR(str) +#define MSO_INTERNAL_WIDE_STR(str) L##str +#define MSO_WIDE_STR(str) MSO_INTERNAL_WIDE_STR(str) #endif -#define MSO_LINE_STR MSO_TO_STR(__LINE__) -#define MSO_LINE_WIDE_STR MSO_WIDE_STR(MSO_LINE_STR) +#define MSO_LINE_STR MSO_TO_STR(__LINE__) +#define MSO_LINE_WIDE_STR MSO_WIDE_STR(MSO_LINE_STR) //============================================================================= // TestCheckFail fails the test unconditionally. //============================================================================= -#define TestCheckFailL(message, line) \ - TestAssert::Fail(MSO_WIDE_STR("Line: " line " " message)) +#define TestCheckFailL(message, line) TestAssert::Fail(MSO_WIDE_STR("Line: " line " " message)) #define TestCheckFail(message) TestCheckFailL(message, MSO_LINE_STR) - //============================================================================= // TestCheck checks if provided expression evaluates to true. // If check fails then it reports the line number and the failed expression. //============================================================================= -#define TestCheckL(expr, line) \ - TestAssert::IsTrue(expr, MSO_WIDE_STR("Line: " line " [ " MSO_TO_STR(expr) " ]")) +#define TestCheckL(expr, line) TestAssert::IsTrue(expr, MSO_WIDE_STR("Line: " line " [ " MSO_TO_STR(expr) " ]")) #define TestCheck(expr) TestCheckL(expr, MSO_LINE_STR) - //============================================================================= // TestCheckEqual checks if two provided values are equal. // If check fails then it reports the line number and the failed expression. // In addition the TestAssert::AreEqual reports expected and actual values. //============================================================================= #define TestCheckEqualL(expected, actual, line) \ - TestAssert::AreEqual(expected, actual, \ - MSO_WIDE_STR("Line: " line " [ " MSO_TO_STR(expected) " == " MSO_TO_STR(actual) " ]")) + TestAssert::AreEqual( \ + expected, actual, MSO_WIDE_STR("Line: " line " [ " MSO_TO_STR(expected) " == " MSO_TO_STR(actual) " ]")) #define TestCheckEqual(expected, actual) TestCheckEqualL(expected, actual, MSO_LINE_STR) - //============================================================================= // TestCheckIgnore ignores the provided expression. // It can be used to avoid compilation errors related to unused variables. @@ -71,17 +66,19 @@ //============================================================================= #define TestCheckIgnore(expr) (void)expr - //============================================================================= // TestCheckCrash expects that the provided expression causes a crash. //============================================================================= // Mso::IgnoreAllAsserts ignore; #define TestCheckCrashL(expr, line) \ - TestAssert::ExpectVEC([&]() { OACR_POSSIBLE_THROW; expr; }, \ - MSO_WIDE_STR("Line: " line " Must crash: [ " MSO_TO_STR(expr) " ]")) + TestAssert::ExpectVEC( \ + [&]() { \ + OACR_POSSIBLE_THROW; \ + expr; \ + }, \ + MSO_WIDE_STR("Line: " line " Must crash: [ " MSO_TO_STR(expr) " ]")) #define TestCheckCrash(expr) TestCheckCrashL(expr, MSO_LINE_STR) - //============================================================================= // TestCheckTerminate expects that the provided expression causes process termination // with a call to std::terminate(). @@ -92,38 +89,28 @@ // You should disable memory leak detection in tests that use TestCheckTerminate. //============================================================================= #define TestCheckTerminateL(expr, line) \ - TestAssert::ExpectTerminate([&]() { expr; }, \ - MSO_WIDE_STR("Line: " line " Must terminate: [ " MSO_TO_STR(expr) " ]")) + TestAssert::ExpectTerminate([&]() { expr; }, MSO_WIDE_STR("Line: " line " Must terminate: [ " MSO_TO_STR(expr) " ]")) #define TestCheckTerminate(expr) TestCheckTerminateL(expr, MSO_LINE_STR) - //============================================================================= // TestCheckException expects that the provided expression throws an exception. //============================================================================= #define TestCheckExceptionL(ex, expr, line) \ - TestAssert::ExpectException([&]() { expr; }, \ - MSO_WIDE_STR("Line: " line " Must throw: " MSO_TO_STR(ex) " [ " MSO_TO_STR(expr) " ]")) + TestAssert::ExpectException( \ + [&]() { expr; }, MSO_WIDE_STR("Line: " line " Must throw: " MSO_TO_STR(ex) " [ " MSO_TO_STR(expr) " ]")) #define TestCheckException(ex, expr) TestCheckExceptionL(ex, expr, MSO_LINE_STR) - //============================================================================= // TestCheckNoThrow expects that the provided expression does not throw an exception. //============================================================================= #define TestCheckNoThrowL(expr, line) \ - TestAssert::ExpectNoThrow([&]() { expr; }, \ - MSO_WIDE_STR("Line: " line " Must not throw: [ " MSO_TO_STR(expr) " ]")) + TestAssert::ExpectNoThrow([&]() { expr; }, MSO_WIDE_STR("Line: " line " Must not throw: [ " MSO_TO_STR(expr) " ]")) #define TestCheckNoThrow(expr) TestCheckNoThrowL(expr, MSO_LINE_STR) - //============================================================================= // TestCheckAssert checks for the code to produce assert with specified tag. //============================================================================= -#define TestCheckShipAssert(tag, expr) \ - Statement( \ - Mso::ExpectShipAssert expectAssert(tag); \ - expr; \ - ); - +#define TestCheckShipAssert(tag, expr) Statement(Mso::ExpectShipAssert expectAssert(tag); expr;); //============================================================================= // A macro to disable memory leak detection in unit tests where we expect crash @@ -134,12 +121,8 @@ // MemoryLeakDetectionHook::TrackPerTest m_trackLeakPerTest; //============================================================================= #define TEST_DISABLE_MEMORY_LEAK_DETECTION() \ - StopTrackingMemoryAllocations(); \ - auto restartTrackingMemoryAllocations = Mso::TCleanup::Make([&]() noexcept \ - { \ - StartTrackingMemoryAllocations(); \ - }); - + StopTrackingMemoryAllocations(); \ + auto restartTrackingMemoryAllocations = Mso::TCleanup::Make([&]() noexcept { StartTrackingMemoryAllocations(); }); //============================================================================= // Helper functions to implement TestCheckTerminate. @@ -148,49 +131,44 @@ namespace TestAssert { struct TerminateHandlerRestorer { - ~TerminateHandlerRestorer() noexcept - { - std::set_terminate(Handler); - } + ~TerminateHandlerRestorer() noexcept + { + std::set_terminate(Handler); + } - std::terminate_handler Handler; + std::terminate_handler Handler; }; #pragma warning(push) -#pragma warning(disable:4611) // interaction between '_setjmp' and C++ object destruction is non-portable +#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable template inline bool ExpectTerminateCore(const Fn& fn) { - static jmp_buf buf; + static jmp_buf buf; - // Set a terminate handler and save the previous terminate handler to be restored in the end of function. - TerminateHandlerRestorer terminateRestore = { - std::set_terminate([]() - { - longjmp(buf, 1); - }) - }; + // Set a terminate handler and save the previous terminate handler to be restored in the end of function. + TerminateHandlerRestorer terminateRestore = {std::set_terminate([]() { longjmp(buf, 1); })}; - // setjmp originally returns 0, and when longjmp is called it returns 1. - if (!setjmp(buf)) - { - fn(); - return false; // must not be executed if fn() caused termination and the longjmp is executed. - } - else - { - return true; // executed if longjmp is executed in the terminate handler. - } + // setjmp originally returns 0, and when longjmp is called it returns 1. + if (!setjmp(buf)) + { + fn(); + return false; // must not be executed if fn() caused termination and the longjmp is executed. + } + else + { + return true; // executed if longjmp is executed in the terminate handler. + } } #pragma warning(pop) template inline void ExpectTerminate(const Fn& fn, const WCHAR* message = L"") { - if (!ExpectTerminateCore(fn)) - { - Fail(message == nullptr || message[0] == L'\0' ? L"Test function did not terminate!" : message); - } + if (!ExpectTerminateCore(fn)) + { + Fail(message == nullptr || message[0] == L'\0' ? L"Test function did not terminate!" : message); + } } } // namespace TestAssert diff --git a/libs/motifCpp/src/gTestMain.cpp b/libs/motifCpp/src/gTestMain.cpp index c5d7901..4220e13 100644 --- a/libs/motifCpp/src/gTestMain.cpp +++ b/libs/motifCpp/src/gTestMain.cpp @@ -3,7 +3,7 @@ #include -int main(int argc, char **argv) +int main(int argc, char** argv) { Mso::UnitTests::GTest::RegisterUnitTests(); ::testing::InitGoogleTest(&argc, argv); diff --git a/libs/oacr/include/oacr.h b/libs/oacr/include/oacr.h index 8ef4432..6cbed6c 100644 --- a/libs/oacr/include/oacr.h +++ b/libs/oacr/include/oacr.h @@ -28,7 +28,7 @@ #endif #if defined(__cplusplus) -#define __extern_c extern "C" +#define __extern_c extern "C" #define __extern_cplus extern "C++" #else #define __extern_c @@ -37,7 +37,7 @@ #ifndef __noreturn #ifndef __clang__ -#define __noreturn __declspec( noreturn ) +#define __noreturn __declspec(noreturn) #else #define __noreturn __attribute__((noreturn)) #endif @@ -51,21 +51,18 @@ #define _Sealed_method_ __oacr_sealed_method #endif // _Sealed_method_ - #if !defined(_Sealed_class_) // use _Sealed_class_ to specify C# style 'sealed' behavior for classes #define _Sealed_class_ __oacr_sealed_class #endif // _Sealed_class_ - #if !defined(_SA_deprecated_) // use _SA_deprecated_ to mark functions or classes that should not be called any more // pass the replacement function or class as an argument to the macro #define _SA_deprecated_(NewFunctionName) __oacr_sa_deprecated(NewFunctionName) #endif // _SA_deprecated_ - -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) // use OACR_MARK_CLASS_DEPRECATED to mark classes that should not be used any more // this macro is a workaround for template classes. Vanilla classes should use _SA_deprecated_ // pass the replacement class as argument to the macro @@ -74,7 +71,6 @@ #define OACR_MARK_CLASS_DEPRECATED(NewFunctionName) #endif - #if !defined(_SA_deprecated_staging_) // use _SA_deprecated_staging_ to mark functions or classes that should not be called any more // pass the replacement function or class as an argument to the macro @@ -83,17 +79,16 @@ #define _SA_deprecated_staging_(NewFunctionName) __oacr_sa_deprecated_staging(NewFunctionName) #endif // _SA_deprecated_staging_ - -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) // use OACR_MARK_CLASS_DEPRECATED_STAGING to mark classes that should not be used any more // this macro is a workaround for template classes. Vanilla classes should use _SA_deprecated_ // pass the replacement function as argument to the macro -#define OACR_MARK_CLASS_DEPRECATED_STAGING(NewFunctionName) _SA_deprecated_staging_(NewFunctionName) void OACRMarkClass(); +#define OACR_MARK_CLASS_DEPRECATED_STAGING(NewFunctionName) \ + _SA_deprecated_staging_(NewFunctionName) void OACRMarkClass(); #else #define OACR_MARK_CLASS_DEPRECATED_STAGING(NewFunctionName) #endif - #if !defined(_Intl_deprecated_) // annotation used by warning UNMARKED_INTL_DEPRECATED_FUNCTION (25114) // to mark deprecated functions using LCID parameters @@ -101,13 +96,11 @@ #define _Intl_deprecated_ __oacr_intl_deprecated #endif // _Intl_deprecated_ - #if !defined(_Oleo_deprecated_) // Office specifix annotation used by the OLEO effort -#define _Oleo_deprecated_( NewFunctionName ) __oacr_oleo_deprecated(NewFunctionName) +#define _Oleo_deprecated_(NewFunctionName) __oacr_oleo_deprecated(NewFunctionName) #endif // _Oleo_deprecated_ - #if !defined(_Norefcapture_asynclambda_) // // use _Norefcapture_asynclambda_ on async function. This warns user of possible unsafe variable capture. @@ -146,7 +139,7 @@ // // Example: // _Noexcept_mayterminate_ignore_("what") void Foo() noexcept; -#define _Noexcept_mayterminate_ignore_(FunctionName) __oacr_noexcept_mayterminate_ignore(FunctionName) +#define _Noexcept_mayterminate_ignore_(FunctionName) __oacr_noexcept_mayterminate_ignore(FunctionName) #endif // _Noexcept_mayterminate_ignore_ #if !defined(_Dont_swap_) @@ -163,33 +156,29 @@ #define _Rpc_ __oacr_rpc #endif // _Rpc_ - #if !defined(_RequireNoThrow_) // use _RequireNoThrow_ inside a compound statement to indicate that the rest of the block // should not emit exceptions. #define _RequireNoThrow_ __oacr_requireNoThrow #endif // _RequireNoThrow_ - #if !defined(_Canthrow_) // use _Canthrow_ for method declarations of template classes that have throwing and non-throwing // specializations to suppress warning FUNC_COULD_BE_NOTHROW (25307). #define _Canthrow_ __oacr_canthrow #endif // __requireNoThrow - #if !defined(_Genericfunctype_) // use _Genericfunctype_ for function typedefs used for arrays of functions of different function types. // if the typedef is marked as _Genericfunctype_, OACR will not generate DIFFERENT_CALLING_CONVENTION (25018) warnings // e.g. typedef _Genericfunctype_ void (*FUNCPTR)(); -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) #define _Genericfunctype_ __oacr_genericfunctype #else #define _Genericfunctype_ #endif #endif // _Genericfunctype_ - #if !defined(_Nothrowfunctype_) // use _Nothrowfunctype_ for function typedefs of non exception throwing function pointers // e.g. typedef _Nothrowfunctype_ void (*FUNCPTR)(); @@ -197,7 +186,6 @@ #define _Nothrowfunctype_ __oacr_nothrowfunctype #endif // _Nothrowfunctype_ - #if !defined(_BindReturn_) // stronger than __checkReturn, typically used by functions that return // a pointer to an allocated object @@ -211,7 +199,6 @@ #define _BindReturn_ __oacr_bindReturn #endif // _BindReturn_ - #if !defined(_Memberinitializer_) // use _Memberinitializer_ for init functions that initialize all members of a class // e.g.: @@ -226,7 +213,6 @@ #define _Memberinitializer_ __oacr_memberinitializer #endif // _Memberinitializer_ - #if !defined(_Noheap_) // use _Noheap_ classes that should not be instantiated on the heap // e.g.: @@ -239,8 +225,7 @@ #define _Noheap_ __oacr_noheap #endif // _Noheap_ - -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) // use OACR_MARK_CLASS_NOHEAP to mark classes that should not be instantiated on the heap // this macro is a workaround for template classes. Vanilla classes should use _Noheap_ #define OACR_MARK_CLASS_NOHEAP _Noheap_ void OACRMarkClass(); @@ -248,7 +233,6 @@ #define OACR_MARK_CLASS_NOHEAP #endif - #if !defined(_Unsafe_string_api_) // use _Unsafe_string_api_ to phase out functions that pass unbound writable buffers // e.g. @@ -256,12 +240,12 @@ #define _Unsafe_string_api_ __oacr_unsafe_string_api #endif // _Unsafe_string_api_ - #if !defined(_Needsreview_) // use _Needsreview_ to mark functions whose calls need to be reviewed for a // special reason. // e.g. a wrapper function to another function that needs to be reviewed -//_Needsreview_ __inline BOOL MsoGetStringTypeExW(LCID Locale, DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType) +//_Needsreview_ __inline BOOL MsoGetStringTypeExW(LCID Locale, DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD +//lpCharType) //{ // return OACR_REVIEWED_CALL("hannesr", GetStringTypeExW(Locale, dwInfoType, lpSrcStr, cchSrc, lpCharType)); //} @@ -269,7 +253,6 @@ #define _Needsreview_ __oacr_needsreview #endif // _Needsreview_ - #if !defined(_Notrunccast_) // use _Notrunccast_ to find unsafe truncating cast on allocating functions taking // a 16 bit size parameter @@ -278,96 +261,95 @@ #define _Notrunccast_ __oacr_notrunccast #endif // _Notrunccast_ - #if !defined(_Noinference_) // keyword to disable (wrong) Hungarian inference of __count annotations // inference is disabled for the all formals of the function // e.g. _Noinference_ void FreePv( void* pv, size_t cb ); -#define _Noinference_ __oacr_noinference +#define _Noinference_ __oacr_noinference #endif // _Noinference_ #if !defined(_Allow_implicit_ctor_) // use _Allow_implicit_ctor_ when a constructors is expected to be implicit. // // e.g. -// +// // _Allow_implicit_ctor_ CPoint( const POINT& ); // #define _Allow_implicit_ctor_ __oacr_allow_implicit_ctor #endif // _Allow_implicit_ctor_ // Pre Orcas style annotations are deprecated -#if( OACR_DEPRECATED ) +#if (OACR_DEPRECATED) #if !defined(__sealed_method) -#define __sealed_method _Sealed_method_ +#define __sealed_method _Sealed_method_ #endif #if !defined(__sealed_class) -#define __sealed_class _Sealed_class_ +#define __sealed_class _Sealed_class_ #endif #if !defined(__sa_deprecated) -#define __sa_deprecated(NewFunctionName) _SA_deprecated_(NewFunctionName) +#define __sa_deprecated(NewFunctionName) _SA_deprecated_(NewFunctionName) #endif #if !defined(__intl_deprecated) -#define __intl_deprecated _Intl_deprecated_ +#define __intl_deprecated _Intl_deprecated_ #endif #if !defined(__oleo_deprecated) -#define __oleo_deprecated( NewFunctionName ) _Oleo_deprecated_(NewFunctionName) +#define __oleo_deprecated(NewFunctionName) _Oleo_deprecated_(NewFunctionName) #endif #if !defined(__rpc) -#define __rpc _Rpc_ +#define __rpc _Rpc_ #endif #if !defined(__requireNoThrow) -#define __requireNoThrow _RequireNoThrow_ +#define __requireNoThrow _RequireNoThrow_ #endif #if !defined(__canthrow) -#define __canthrow _Canthrow_ +#define __canthrow _Canthrow_ #endif #if !defined(__genericfunctype) -#define __genericfunctype _Genericfunctype_ +#define __genericfunctype _Genericfunctype_ #endif #if !defined(__nothrowfunctype) -#define __nothrowfunctype _Nothrowfunctype_ +#define __nothrowfunctype _Nothrowfunctype_ #endif #if !defined(__bindReturn) -#define __bindReturn _BindReturn_ +#define __bindReturn _BindReturn_ #endif #if !defined(__memberinitializer) -#define __memberinitializer _Memberinitializer_ +#define __memberinitializer _Memberinitializer_ #endif #if !defined(__noheap) -#define __noheap _Noheap_ +#define __noheap _Noheap_ #endif #if !defined(__nostack) -#define __nostack // not supported +#define __nostack // not supported #endif #if !defined(__unsafe_string_api) -#define __unsafe_string_api _Unsafe_string_api_ +#define __unsafe_string_api _Unsafe_string_api_ #endif #if !defined(__needsreview) -#define __needsreview _Needsreview_ +#define __needsreview _Needsreview_ #endif #if !defined(__notrunccast) -#define __notrunccast _Notrunccast_ +#define __notrunccast _Notrunccast_ #endif #if !defined(__noinference) -#define __noinference _Noinference_ +#define __noinference _Noinference_ #endif #if !defined(__min_function) -#define __min_function // deprecated, use range annotations +#define __min_function // deprecated, use range annotations #endif #if !defined(__max_function) -#define __max_function // deprecated, use range annotations +#define __max_function // deprecated, use range annotations #endif #if !defined(__printf_format_string) -#define __printf_format_string _Printf_format_string_ +#define __printf_format_string _Printf_format_string_ #endif #undef __callback -#define __callback _Callback_ +#define __callback _Callback_ #if !defined(__sa_sealed) // use __sealed_method and __sealed_class instead -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) #define __sa_sealed __declspec("_Sealed_") #else #define __sa_sealed @@ -382,13 +364,13 @@ #if !defined(OACR_USE_PTR) // use to suppress constness and related warnings: -// NONCONST_LOCAL (25003), NONCONST_PARAM( 25004), NONCONST_FUNCTION (25005), +// NONCONST_LOCAL (25003), NONCONST_PARAM( 25004), NONCONST_FUNCTION (25005), // NONCONST_LOCAL_BUFFERPTR (25032), NONCONST_BUFFER_PARAM (25033) -#if( defined(OACR) && OACR ) -__extern_c void OACRUsePtr( void* p ); -#define OACR_USE_PTR( p ) OACRUsePtr( p ) +#if (defined(OACR) && OACR) +__extern_c void OACRUsePtr(void* p); +#define OACR_USE_PTR(p) OACRUsePtr(p) #else -#define OACR_USE_PTR( p ) __oacr_noop() +#define OACR_USE_PTR(p) __oacr_noop() #endif #endif // OACR_USE_PTR @@ -400,7 +382,7 @@ __extern_c void OACRUsePtr( void* p ); // is spread across both ctor initializer list and a _Memberinitializer_ method). // NOTES: This is functionally to OACR_USE_PTR(&m). // Contrast with OACR_MEMBER_IS_INITIALIZED_IN_MEMBERINITIALIZER. -#define OACR_MEMBER_IS_INITIALIZED_IN_CTOR( m ) OACR_USE_PTR( &m ) +#define OACR_MEMBER_IS_INITIALIZED_IN_CTOR(m) OACR_USE_PTR(&m) #endif // OACR_MEMBER_IS_INITIALIZED_IN_CTOR #if !defined(OACR_MEMBER_IS_INITIALIZED_IN_MEMBERINITIALIZER) @@ -410,13 +392,13 @@ __extern_c void OACRUsePtr( void* p ); // is spread across both ctor initializer list and a _Memberinitializer_ method). // NOTES: This is functionally equivalent to OACR_USE_PTR(&m). // Contrast with OACR_MEMBER_IS_INITIALIZED_IN_CTOR. -#define OACR_MEMBER_IS_INITIALIZED_IN_MEMBERINITIALIZER( m ) OACR_USE_PTR( &m ) +#define OACR_MEMBER_IS_INITIALIZED_IN_MEMBERINITIALIZER(m) OACR_USE_PTR(&m) #endif // OACR_MEMBER_IS_INITIALIZED_IN_MEMBERINITIALIZER #endif // !RC_INVOKED #if !defined(OACR_POSSIBLE_THROW) // use to suppress __nothrow related warnings NOTHROW_FUNC_THROWS (25306) and FUNC_COULD_BE_NOTHROW (25307) -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) __extern_cplus void OACRPossibleThrow(); #define OACR_POSSIBLE_THROW OACRPossibleThrow() #else @@ -425,12 +407,19 @@ __extern_cplus void OACRPossibleThrow(); #endif // OACR_POSSIBLE_THROW #if !defined(OACR_ASSUME_NOTHROW_BEGIN) -// use with OACR_ASSUME_NOTHROW_END to suppress NOTHROW_FUNC_THROWS warnings around functions that don't throw in this context -// macro pair needs to be on the same scope -#if( defined(OACR) && OACR ) +// use with OACR_ASSUME_NOTHROW_END to suppress NOTHROW_FUNC_THROWS warnings around functions that don't throw in this +// context macro pair needs to be on the same scope +#if (defined(OACR) && OACR) __extern_c __noreturn void OACRNoReturn(); -#define OACR_ASSUME_NOTHROW_BEGIN try{ -#define OACR_ASSUME_NOTHROW_END }catch(...){ OACRNoReturn(); } +#define OACR_ASSUME_NOTHROW_BEGIN \ + try \ + { +#define OACR_ASSUME_NOTHROW_END \ + } \ + catch (...) \ + { \ + OACRNoReturn(); \ + } #else #define OACR_ASSUME_NOTHROW_BEGIN #define OACR_ASSUME_NOTHROW_END @@ -439,86 +428,81 @@ __extern_c __noreturn void OACRNoReturn(); #if !defined(UNREFERENCED_OACR) // use to function staticness and related warnings: STATIC_FUNCTION (25007) -#if( defined(OACR) && OACR ) -#define UNREFERENCED_OACR( p ) __assume( p == p ) +#if (defined(OACR) && OACR) +#define UNREFERENCED_OACR(p) __assume(p == p) #else -#define UNREFERENCED_OACR( p ) +#define UNREFERENCED_OACR(p) #endif #endif // UNREFERENCED_OACR - #if !defined(OACR_OWN_PTR) // can be used for objects that attach themselves to an owner // in their constructors -#if( defined(OACR) && OACR ) -__extern_c void OACROwnPtr( const void* p ); -#define OACR_OWN_PTR( p ) OACROwnPtr( p ) +#if (defined(OACR) && OACR) +__extern_c void OACROwnPtr(const void* p); +#define OACR_OWN_PTR(p) OACROwnPtr(p) #else -#define OACR_OWN_PTR( p ) __oacr_noop() +#define OACR_OWN_PTR(p) __oacr_noop() #endif #endif // OACR_OWN_PTR - #if !defined(OACR_PTR_NOT_NULL) // tells OACR that a pointer is not null at this point -#if( defined(OACR) && OACR ) -#define OACR_PTR_NOT_NULL( p ) OACR_ASSUME( 0 != p ) +#if (defined(OACR) && OACR) +#define OACR_PTR_NOT_NULL(p) OACR_ASSUME(0 != p) #else -#define OACR_PTR_NOT_NULL( p ) __oacr_noop() +#define OACR_PTR_NOT_NULL(p) __oacr_noop() #endif #endif // OACR_PTR_NOT_NULL - #if !defined(OACR_NOT_IMPLEMENTED_MEMBER) -#if( defined(OACR) && OACR ) -#define OACR_NOT_IMPLEMENTED_MEMBER OACR_USE_PTR( (void*)this ) +#if (defined(OACR) && OACR) +#define OACR_NOT_IMPLEMENTED_MEMBER OACR_USE_PTR((void*)this) #else #define OACR_NOT_IMPLEMENTED_MEMBER #endif #endif // OACR_NOT_IMPLEMENTED_MEMBER - #if !defined(OACR_DECLARE_FILLER) -#if( defined(OACR) && OACR ) -#define OACR_DECLARE_FILLER( type, inst ) type __filler##inst; +#if (defined(OACR) && OACR) +#define OACR_DECLARE_FILLER(type, inst) type __filler##inst; #else -#define OACR_DECLARE_FILLER( type, inst ) +#define OACR_DECLARE_FILLER(type, inst) #endif #endif // OACR_DECLARE_FILLER - // use this macro once you have inspected warnings FUNCTION_NEEDS_REVIEW (25028) #if !defined(OACR_REVIEWED_CALL) -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) __extern_c void __OACRReviewedCall(); -#define OACR_REVIEWED_CALL( reviewer, functionCall ) ( __OACRReviewedCall(), functionCall ) +#define OACR_REVIEWED_CALL(reviewer, functionCall) (__OACRReviewedCall(), functionCall) #else -#define OACR_REVIEWED_CALL( reviewer, functionCall ) functionCall +#define OACR_REVIEWED_CALL(reviewer, functionCall) functionCall #endif #endif // OACR_REVIEWED_CALL - // use this macro once you have inspected warnings URL_NEEDS_TO_BE_REVIEWED (25085) #if !defined(OACR_REVIEWED_URL) -#if( defined(OACR) && OACR ) +#if (defined(OACR) && OACR) __extern_c void __OACRReviewedUrl(); -#define OACR_REVIEWED_URL( reviewer, reviewedUrl ) ( __OACRReviewedUrl(), reviewedUrl ) +#define OACR_REVIEWED_URL(reviewer, reviewedUrl) (__OACRReviewedUrl(), reviewedUrl) #else -#define OACR_REVIEWED_URL( reviewer, reviewedUrl ) reviewedUrl +#define OACR_REVIEWED_URL(reviewer, reviewedUrl) reviewedUrl #endif #endif // OACR_REVIEWED_URL #if !defined(OACR_DONT_SWAP) -// use to suppress warnings MISSING_MEMBER_SWAP (25146) for nonswappable data members like refcounts, critical sections, etc. -#if( defined(OACR) && OACR ) -__extern_c void OACRDontSwap( void* p ); -#define OACR_DONT_SWAP( m ) OACRDontSwap( &( m ) ) +// use to suppress warnings MISSING_MEMBER_SWAP (25146) for nonswappable data members like refcounts, critical sections, +// etc. +#if (defined(OACR) && OACR) +__extern_c void OACRDontSwap(void* p); +#define OACR_DONT_SWAP(m) OACRDontSwap(&(m)) #else -#define OACR_DONT_SWAP( m ) __oacr_noop() +#define OACR_DONT_SWAP(m) __oacr_noop() #endif #endif // OACR_DONT_SWAP -#if( defined(OACR) && OACR && defined(_WINDEF_) && 0 ) +#if (defined(OACR) && OACR && defined(_WINDEF_) && 0) // redefine FALSE & TRUE for better HRESULT<->BOOL conversion detection #if defined(FALSE) @@ -543,11 +527,11 @@ __extern_c void OACRDontSwap( void* p ); // p->Foo(); #if !defined(OACR_WARNING_PUSH) -#if( defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS) ) -#if( 1400 <=_MSC_VER ) -#define OACR_WARNING_PUSH __pragma ( warning( push ) ) +#if (defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS)) +#if (1400 <= _MSC_VER) +#define OACR_WARNING_PUSH __pragma(warning(push)) #else -#define OACR_WARNING_PUSH __pragma ( prefast( push ) ) +#define OACR_WARNING_PUSH __pragma(prefast(push)) #endif #else #define OACR_WARNING_PUSH @@ -555,11 +539,11 @@ __extern_c void OACRDontSwap( void* p ); #endif #if !defined(OACR_WARNING_POP) -#if( defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS) ) -#if( 1400 <=_MSC_VER ) -#define OACR_WARNING_POP __pragma ( warning( pop ) ) +#if (defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS)) +#if (1400 <= _MSC_VER) +#define OACR_WARNING_POP __pragma(warning(pop)) #else -#define OACR_WARNING_POP __pragma ( prefast( pop ) ) +#define OACR_WARNING_POP __pragma(prefast(pop)) #endif #else #define OACR_WARNING_POP @@ -567,38 +551,38 @@ __extern_c void OACRDontSwap( void* p ); #endif #if !defined(OACR_WARNING_ENABLE) -#if( defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS) ) -#if( 1400 <=_MSC_VER ) -#define OACR_WARNING_ENABLE( cWarning, comment ) __pragma ( warning( default: __WARNING_##cWarning ) ) +#if (defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS)) +#if (1400 <= _MSC_VER) +#define OACR_WARNING_ENABLE(cWarning, comment) __pragma(warning(default : __WARNING_##cWarning)) #else -#define OACR_WARNING_ENABLE( cWarning, comment ) +#define OACR_WARNING_ENABLE(cWarning, comment) #endif #else -#define OACR_WARNING_ENABLE( cWarning, comment ) +#define OACR_WARNING_ENABLE(cWarning, comment) #endif #endif #if !defined(OACR_WARNING_DISABLE) -#if( defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS) ) -#if( 1400 <=_MSC_VER ) -#define OACR_WARNING_DISABLE( cWarning, comment ) __pragma ( warning( disable: __WARNING_##cWarning ) ) +#if (defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS)) +#if (1400 <= _MSC_VER) +#define OACR_WARNING_DISABLE(cWarning, comment) __pragma(warning(disable : __WARNING_##cWarning)) #else -#define OACR_WARNING_DISABLE( cWarning, comment ) __pragma ( prefast( disable: __WARNING_##cWarning, comment ) ) +#define OACR_WARNING_DISABLE(cWarning, comment) __pragma(prefast(disable : __WARNING_##cWarning, comment)) #endif #else -#define OACR_WARNING_DISABLE( cWarning, comment ) +#define OACR_WARNING_DISABLE(cWarning, comment) #endif #endif #if !defined(OACR_WARNING_SUPPRESS) -#if( defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS) ) -#if( 1400 <=_MSC_VER ) -#define OACR_WARNING_SUPPRESS( cWarning, comment ) __pragma ( warning( suppress: __WARNING_##cWarning ) ) +#if (defined(OACR) && OACR && !defined(OACR_NO_WARNING_MACROS)) +#if (1400 <= _MSC_VER) +#define OACR_WARNING_SUPPRESS(cWarning, comment) __pragma(warning(suppress : __WARNING_##cWarning)) #else -#define OACR_WARNING_SUPPRESS( cWarning, comment ) __pragma ( prefast( suppress: __WARNING_##cWarning, comment) ) +#define OACR_WARNING_SUPPRESS(cWarning, comment) __pragma(prefast(suppress : __WARNING_##cWarning, comment)) #endif #else -#define OACR_WARNING_SUPPRESS( cWarning, comment ) +#define OACR_WARNING_SUPPRESS(cWarning, comment) #endif #endif @@ -608,54 +592,53 @@ __extern_c void OACRDontSwap( void* p ); // if( g_pRoot == NULL ) // global variable g_pRoot // { // InitRoot(); -// OACR_ASSUME( NULL != g_pRoot ); +// OACR_ASSUME( NULL != g_pRoot ); // } // g_pRoot->Traverse(); // without OACR_ASSUME this would cause warning 11 -#if( defined(OACR) && OACR ) -#define OACR_ASSUME( fCondition ) __assume( fCondition ) +#if (defined(OACR) && OACR) +#define OACR_ASSUME(fCondition) __assume(fCondition) #elif defined(Assert) -#define OACR_ASSUME( fCondition ) Assert( fCondition ) +#define OACR_ASSUME(fCondition) Assert(fCondition) #else -#define OACR_ASSUME( fCondition ) __oacr_noop() +#define OACR_ASSUME(fCondition) __oacr_noop() #endif // macro to tell OACR that a string is null terminated at this point of execution -#if( defined(OACR) && OACR && defined(_Post_z_) ) -__extern_c void __OACRAssumeNullterminated( _Post_z_ const char* sz ); -#define OACR_ASSUME_NULLTERMINATED( string ) __OACRAssumeNullterminated( (const char*)string ) +#if (defined(OACR) && OACR && defined(_Post_z_)) +__extern_c void __OACRAssumeNullterminated(_Post_z_ const char* sz); +#define OACR_ASSUME_NULLTERMINATED(string) __OACRAssumeNullterminated((const char*)string) #else -#define OACR_ASSUME_NULLTERMINATED( string ) __oacr_noop() +#define OACR_ASSUME_NULLTERMINATED(string) __oacr_noop() #endif // macro to tell OACR that a pointer is null valid at this point of execution -#if( defined(OACR) && OACR && defined(_Post_valid_) ) -__extern_c void __OACRAssumeValid( _Post_valid_ const void* pv ); -#define OACR_ASSUME_VALID( ptr ) __OACRAssumeValid( ptr ) +#if (defined(OACR) && OACR && defined(_Post_valid_)) +__extern_c void __OACRAssumeValid(_Post_valid_ const void* pv); +#define OACR_ASSUME_VALID(ptr) __OACRAssumeValid(ptr) #else -#define OACR_ASSUME_VALID( ptr ) __oacr_noop() +#define OACR_ASSUME_VALID(ptr) __oacr_noop() #endif - // macro to tell OACR that a buffer has a certain readable extent at this point of execution // it can be used to silent noisy espX INCORRECT_ANNOTATION warnings -#if( defined(OACR) && OACR && defined(_Post_bytecount_) ) -__extern_c void __OACRAssumeByteCount( _Post_bytecount_(cb) const void* pv, size_t cb ); -#define OACR_ASSUME_BYTECOUNT( pv, cb ) __OACRAssumeByteCount( pv, cb ) +#if (defined(OACR) && OACR && defined(_Post_bytecount_)) +__extern_c void __OACRAssumeByteCount(_Post_bytecount_(cb) const void* pv, size_t cb); +#define OACR_ASSUME_BYTECOUNT(pv, cb) __OACRAssumeByteCount(pv, cb) #else -#define OACR_ASSUME_BYTECOUNT( pv, cb ) __oacr_noop() +#define OACR_ASSUME_BYTECOUNT(pv, cb) __oacr_noop() #endif // macro indicate lambda mayterminate -#if( defined(OACR) && OACR && defined(__cplusplus)) +#if (defined(OACR) && OACR && defined(__cplusplus)) void _lambda_noexcept_mayterminate_() noexcept {}; #define OACR_LAMBDA_NOEXCEPT_MAYTERMINATE _lambda_noexcept_mayterminate_() #define OACR_NOEXCEPT_MAYTERMINATE _lambda_noexcept_mayterminate_() @@ -665,7 +648,7 @@ void _lambda_noexcept_mayterminate_() noexcept {}; #endif // macro indicate mayterminate ignore stl -#if( defined(OACR) && OACR && defined(__cplusplus)) +#if (defined(OACR) && OACR && defined(__cplusplus)) void _noexcept_mayterminate_ignore_stl_() noexcept {}; #define OACR_NOEXCEPT_MAYTERMINATE_IGNORE_STL _noexcept_mayterminate_ignore_stl_() #else @@ -673,28 +656,28 @@ void _noexcept_mayterminate_ignore_stl_() noexcept {}; #endif // macro indicate mayterminate ignore -#if( defined(OACR) && OACR && defined(__cplusplus)) +#if (defined(OACR) && OACR && defined(__cplusplus)) __extern_c void _noexcept_mayterminate_ignore_(const char*) noexcept; -#define OACR_NOEXCEPT_MAYTERMINATE_IGNORE( funcs ) _noexcept_mayterminate_ignore_(funcs) +#define OACR_NOEXCEPT_MAYTERMINATE_IGNORE(funcs) _noexcept_mayterminate_ignore_(funcs) #else -#define OACR_NOEXCEPT_MAYTERMINATE_IGNORE( funcs ) __oacr_noop() +#define OACR_NOEXCEPT_MAYTERMINATE_IGNORE(funcs) __oacr_noop() #endif // OACR custom plugin specific extensions //======================================================================= -#define _Callback_ __oacr_callback +#define _Callback_ __oacr_callback //====================================================================== // OACR custom attributes // OACR custom plugin specific extensions -#if( _USE_DECLSPECS_FOR_SAL ) +#if (_USE_DECLSPECS_FOR_SAL) #ifndef _SA_SPECSTRIZE -#define _SA_SPECSTRIZE( x ) #x +#define _SA_SPECSTRIZE(x) #x #endif __ANNOTATION(_Callback_(void)); @@ -707,8 +690,8 @@ __ANNOTATION(_Intl_deprecated_(void)); __ANNOTATION(_Noinference_(void)); __ANNOTATION(_Canthrow_(void)); __ANNOTATION(_BindReturn_(void)); -__ANNOTATION(_SA_deprecated_(__AuToQuOtE char *)); -__ANNOTATION(_Oleo_deprecated_(__AuToQuOtE char *)); +__ANNOTATION(_SA_deprecated_(__AuToQuOtE char*)); +__ANNOTATION(_Oleo_deprecated_(__AuToQuOtE char*)); __ANNOTATION(_Genericfunctype_(void)); __ANNOTATION(__nothrowfunctype(void)); __ANNOTATION(_Noheap_(void)); @@ -717,36 +700,38 @@ __ANNOTATION(_Sealed_(void)); __ANNOTATION(_Allow_implicit_ctor_(void)); __ANNOTATION(_Norefcapture_asynclambda_(void)); __ANNOTATION(_Nodecl_lambda_(void)); -__ANNOTATION(_Noexcept_maythrow_( void ) ); -__ANNOTATION(_Noexcept_mayterminate_( void )); -__ANNOTATION(_Noexcept_mayterminate_ignore_( __AuToQuOtE char * )); -__ANNOTATION(_Dont_swap_( void )); +__ANNOTATION(_Noexcept_maythrow_(void)); +__ANNOTATION(_Noexcept_mayterminate_(void)); +__ANNOTATION(_Noexcept_mayterminate_ignore_(__AuToQuOtE char*)); +__ANNOTATION(_Dont_swap_(void)); -#define __oacr_callback __declspec("_Callback_") -#define __oacr_rpc __declspec("_Rpc_") -#define __oacr_sealed_method __declspec("_Sealed_") -#define __oacr_memberinitializer __declspec("_Memberinitializer_") -#define __oacr_unsafe_string_api __declspec("_Unsafe_string_api_") -#define __oacr_needsreview __declspec("_Needsreview_") -#define __oacr_intl_deprecated __declspec("_Intl_deprecated_") -#define __oacr_noinference __declspec("_Noinference_") -#define __oacr_canthrow __declspec("_Canthrow_") -#define __oacr_bindReturn __declspec("_BindReturn_") -#define __oacr_sa_deprecated(NewFunctionName) __declspec("_SA_deprecated_("_SA_SPECSTRIZE(NewFunctionName)")") -#define __oacr_sa_deprecated_staging(NewFunctionName) __declspec("_SA_deprecated_staging_("_SA_SPECSTRIZE(NewFunctionName)")") -#define __oacr_oleo_deprecated(NewFunctionName) __declspec("_Oleo_deprecated_("_SA_SPECSTRIZE(NewFunctionName)")") -#define __oacr_genericfunctype __declspec("_Genericfunctype_") -#define __oacr_nothrowfunctype __declspec("__nothrowfunctype") -#define __oacr_noheap __declspec("_Noheap_") -#define __oacr_notrunccast __declspec("_Notrunccast_") -#define __oacr_sealed_class __declspec("_Sealed_") -#define __oacr_allow_implicit_ctor __declspec("_Allow_implicit_ctor_") -#define __oacr_norefcapture_asynclambda __declspec("_Norefcapture_asynclambda_") -#define __oacr_nodecl_lambda __declspec("_Nodecl_lambda_") -#define __oacr_noexcept_maythrow __declspec("_Noexcept_maythrow_") -#define __oacr_noexcept_mayterminate __declspec("_Noexcept_mayterminate_") -#define __oacr_noexcept_mayterminate_ignore(FunctionName) __declspec("_Noexcept_mayterminate_ignore_("_SA_SPECSTRIZE(FunctionName)")") -#define __oacr_dont_swap __declspec("_Dont_swap_") +#define __oacr_callback __declspec("_Callback_") +#define __oacr_rpc __declspec("_Rpc_") +#define __oacr_sealed_method __declspec("_Sealed_") +#define __oacr_memberinitializer __declspec("_Memberinitializer_") +#define __oacr_unsafe_string_api __declspec("_Unsafe_string_api_") +#define __oacr_needsreview __declspec("_Needsreview_") +#define __oacr_intl_deprecated __declspec("_Intl_deprecated_") +#define __oacr_noinference __declspec("_Noinference_") +#define __oacr_canthrow __declspec("_Canthrow_") +#define __oacr_bindReturn __declspec("_BindReturn_") +#define __oacr_sa_deprecated(NewFunctionName) __declspec("_SA_deprecated_("_SA_SPECSTRIZE(NewFunctionName) ")") +#define __oacr_sa_deprecated_staging(NewFunctionName) \ + __declspec("_SA_deprecated_staging_("_SA_SPECSTRIZE(NewFunctionName) ")") +#define __oacr_oleo_deprecated(NewFunctionName) __declspec("_Oleo_deprecated_("_SA_SPECSTRIZE(NewFunctionName) ")") +#define __oacr_genericfunctype __declspec("_Genericfunctype_") +#define __oacr_nothrowfunctype __declspec("__nothrowfunctype") +#define __oacr_noheap __declspec("_Noheap_") +#define __oacr_notrunccast __declspec("_Notrunccast_") +#define __oacr_sealed_class __declspec("_Sealed_") +#define __oacr_allow_implicit_ctor __declspec("_Allow_implicit_ctor_") +#define __oacr_norefcapture_asynclambda __declspec("_Norefcapture_asynclambda_") +#define __oacr_nodecl_lambda __declspec("_Nodecl_lambda_") +#define __oacr_noexcept_maythrow __declspec("_Noexcept_maythrow_") +#define __oacr_noexcept_mayterminate __declspec("_Noexcept_mayterminate_") +#define __oacr_noexcept_mayterminate_ignore(FunctionName) \ + __declspec("_Noexcept_mayterminate_ignore_("_SA_SPECSTRIZE(FunctionName) ")") +#define __oacr_dont_swap __declspec("_Dont_swap_") __extern_c int __RequireNoThrow(); #define __oacr_requireNoThrow __RequireNoThrow(); diff --git a/libs/oacr/include/oacrsal.h b/libs/oacr/include/oacrsal.h index 5b3f3fb..56e52d2 100644 --- a/libs/oacr/include/oacrsal.h +++ b/libs/oacr/include/oacrsal.h @@ -25,207 +25,349 @@ // Annotations for _t (pascal string) and _tz (nullterminated pascal string) -#define _In_t_ _Pre_t_ _Deref_pre_readonly_ -#define _In_opt_t_ _Pre_opt_t_ _Deref_pre_readonly_ -#define _In_tz_ _Pre_tz_ _Deref_pre_readonly_ -#define _In_opt_tz_ _Pre_opt_tz_ _Deref_pre_readonly_ +#define _In_t_ _Pre_t_ _Deref_pre_readonly_ +#define _In_opt_t_ _Pre_opt_t_ _Deref_pre_readonly_ +#define _In_tz_ _Pre_tz_ _Deref_pre_readonly_ +#define _In_opt_tz_ _Pre_opt_tz_ _Deref_pre_readonly_ -#define _Out_t_cap_(size) _Pre_cap_(size) _Pre_invalid_ _Post_t_ -#define _Out_opt_t_cap_(size) _Pre_opt_cap_(size) _Pre_invalid_ _Post_t_ -#define _Out_t_bytecap_(size) _Pre_bytecap_(size) _Pre_invalid_ _Post_t_ -#define _Out_opt_t_bytecap_(size) _Pre_opt_bytecap_(size) _Pre_invalid_ _Post_t_ -#define _Out_tz_cap_(size) _Pre_cap_(size) _Pre_invalid_ _Post_tz_ -#define _Out_opt_tz_cap_(size) _Pre_opt_cap_(size) _Pre_invalid_ _Post_tz_ -#define _Out_tz_bytecap_(size) _Pre_bytecap_(size) _Pre_invalid_ _Post_tz_ -#define _Out_opt_tz_bytecap_(size) _Pre_opt_bytecap_(size) _Pre_invalid_ _Post_tz_ +#define _Out_t_cap_(size) _Pre_cap_(size) _Pre_invalid_ _Post_t_ +#define _Out_opt_t_cap_(size) _Pre_opt_cap_(size) _Pre_invalid_ _Post_t_ +#define _Out_t_bytecap_(size) _Pre_bytecap_(size) _Pre_invalid_ _Post_t_ +#define _Out_opt_t_bytecap_(size) _Pre_opt_bytecap_(size) _Pre_invalid_ _Post_t_ +#define _Out_tz_cap_(size) _Pre_cap_(size) _Pre_invalid_ _Post_tz_ +#define _Out_opt_tz_cap_(size) _Pre_opt_cap_(size) _Pre_invalid_ _Post_tz_ +#define _Out_tz_bytecap_(size) _Pre_bytecap_(size) _Pre_invalid_ _Post_tz_ +#define _Out_opt_tz_bytecap_(size) _Pre_opt_bytecap_(size) _Pre_invalid_ _Post_tz_ -#define _Out_t_cap_c_(size) _Pre_cap_c_(size) _Pre_invalid_ _Post_t_ -#define _Out_opt_t_cap_c_(size) _Pre_opt_cap_c_(size) _Pre_invalid_ _Post_t_ -#define _Out_t_bytecap_c_(size) _Pre_bytecap_c_(size) _Pre_invalid_ _Post_t_ -#define _Out_opt_t_bytecap_c_(size) _Pre_opt_bytecap_c_(size) _Pre_invalid_ _Post_t_ -#define _Out_tz_cap_c_(size) _Pre_cap_c_(size) _Pre_invalid_ _Post_tz_ -#define _Out_opt_tz_cap_c_(size) _Pre_opt_cap_c_(size) _Pre_invalid_ _Post_tz_ -#define _Out_tz_bytecap_c_(size) _Pre_bytecap_c_(size) _Pre_invalid_ _Post_tz_ -#define _Out_opt_tz_bytecap_c_(size) _Pre_opt_bytecap_c_(size) _Pre_invalid_ _Post_tz_ +#define _Out_t_cap_c_(size) _Pre_cap_c_(size) _Pre_invalid_ _Post_t_ +#define _Out_opt_t_cap_c_(size) _Pre_opt_cap_c_(size) _Pre_invalid_ _Post_t_ +#define _Out_t_bytecap_c_(size) _Pre_bytecap_c_(size) _Pre_invalid_ _Post_t_ +#define _Out_opt_t_bytecap_c_(size) _Pre_opt_bytecap_c_(size) _Pre_invalid_ _Post_t_ +#define _Out_tz_cap_c_(size) _Pre_cap_c_(size) _Pre_invalid_ _Post_tz_ +#define _Out_opt_tz_cap_c_(size) _Pre_opt_cap_c_(size) _Pre_invalid_ _Post_tz_ +#define _Out_tz_bytecap_c_(size) _Pre_bytecap_c_(size) _Pre_invalid_ _Post_tz_ +#define _Out_opt_tz_bytecap_c_(size) _Pre_opt_bytecap_c_(size) _Pre_invalid_ _Post_tz_ -#define _Out_t_cap_x_(size) _Pre_cap_x_(size) _Pre_invalid_ _Post_t_ -#define _Out_opt_t_cap_x_(size) _Pre_opt_cap_x_(size) _Pre_invalid_ _Post_t_ -#define _Out_t_bytecap_x_(size) _Pre_bytecap_x_(size) _Pre_invalid_ _Post_t_ -#define _Out_opt_t_bytecap_x_(size) _Pre_opt_bytecap_x_(size) _Pre_invalid_ _Post_t_ -#define _Out_tz_cap_x_(size) _Pre_cap_x_(size) _Pre_invalid_ _Post_tz_ -#define _Out_opt_tz_cap_x_(size) _Pre_opt_cap_x_(size) _Pre_invalid_ _Post_tz_ -#define _Out_tz_bytecap_x_(size) _Pre_bytecap_x_(size) _Pre_invalid_ _Post_tz_ -#define _Out_opt_tz_bytecap_x_(size) _Pre_opt_bytecap_x_(size) _Pre_invalid_ _Post_tz_ +#define _Out_t_cap_x_(size) _Pre_cap_x_(size) _Pre_invalid_ _Post_t_ +#define _Out_opt_t_cap_x_(size) _Pre_opt_cap_x_(size) _Pre_invalid_ _Post_t_ +#define _Out_t_bytecap_x_(size) _Pre_bytecap_x_(size) _Pre_invalid_ _Post_t_ +#define _Out_opt_t_bytecap_x_(size) _Pre_opt_bytecap_x_(size) _Pre_invalid_ _Post_t_ +#define _Out_tz_cap_x_(size) _Pre_cap_x_(size) _Pre_invalid_ _Post_tz_ +#define _Out_opt_tz_cap_x_(size) _Pre_opt_cap_x_(size) _Pre_invalid_ _Post_tz_ +#define _Out_tz_bytecap_x_(size) _Pre_bytecap_x_(size) _Pre_invalid_ _Post_tz_ +#define _Out_opt_tz_bytecap_x_(size) _Pre_opt_bytecap_x_(size) _Pre_invalid_ _Post_tz_ -#define _Out_tz_cap_post_count_(cap,count) _Pre_cap_(cap) _Pre_invalid_ _Post_tz_count_(count) -#define _Out_opt_tz_cap_post_count_(cap,count) _Pre_opt_cap_(cap) _Pre_invalid_ _Post_tz_count_(count) -#define _Out_tz_bytecap_post_bytecount_(cap,count) _Pre_bytecap_(cap) _Pre_invalid_ _Post_tz_bytecount_(count) -#define _Out_opt_tz_bytecap_post_bytecount_(cap,count) _Pre_opt_bytecap_(cap) _Pre_invalid_ _Post_tz_bytecount_(count) +#define _Out_tz_cap_post_count_(cap, count) _Pre_cap_(cap) _Pre_invalid_ _Post_tz_count_(count) +#define _Out_opt_tz_cap_post_count_(cap, count) _Pre_opt_cap_(cap) _Pre_invalid_ _Post_tz_count_(count) +#define _Out_tz_bytecap_post_bytecount_(cap, count) _Pre_bytecap_(cap) _Pre_invalid_ _Post_tz_bytecount_(count) +#define _Out_opt_tz_bytecap_post_bytecount_(cap, count) _Pre_opt_bytecap_(cap) _Pre_invalid_ _Post_tz_bytecount_(count) -#define _Out_tz_capcount_(capcount) _Pre_cap_(capcount) _Pre_invalid_ _Post_tz_count_(capcount) -#define _Out_opt_tz_capcount_(capcount) _Pre_opt_cap_(capcount) _Pre_invalid_ _Post_tz_count_(capcount) -#define _Out_tz_bytecapcount_(capcount) _Pre_bytecap_(capcount) _Pre_invalid_ _Post_tz_bytecount_(capcount) -#define _Out_opt_tz_bytecapcount_(capcount) _Pre_opt_bytecap_(capcount) _Pre_invalid_ _Post_tz_bytecount_(capcount) +#define _Out_tz_capcount_(capcount) _Pre_cap_(capcount) _Pre_invalid_ _Post_tz_count_(capcount) +#define _Out_opt_tz_capcount_(capcount) _Pre_opt_cap_(capcount) _Pre_invalid_ _Post_tz_count_(capcount) +#define _Out_tz_bytecapcount_(capcount) _Pre_bytecap_(capcount) _Pre_invalid_ _Post_tz_bytecount_(capcount) +#define _Out_opt_tz_bytecapcount_(capcount) _Pre_opt_bytecap_(capcount) _Pre_invalid_ _Post_tz_bytecount_(capcount) -#define _Inout_t_ _Prepost_t_ -#define _Inout_opt_t_ _Prepost_opt_t_ -#define _Inout_tz_ _Prepost_tz_ -#define _Inout_opt_tz_ _Prepost_opt_tz_ +#define _Inout_t_ _Prepost_t_ +#define _Inout_opt_t_ _Prepost_opt_t_ +#define _Inout_tz_ _Prepost_tz_ +#define _Inout_opt_tz_ _Prepost_opt_tz_ -#define _Inout_t_cap_(size) _Pre_t_cap_(size) _Post_t_ -#define _Inout_opt_t_cap_(size) _Pre_opt_t_cap_(size) _Post_t_ -#define _Inout_t_bytecap_(size) _Pre_t_bytecap_(size) _Post_t_ -#define _Inout_opt_t_bytecap_(size) _Pre_opt_t_bytecap_(size) _Post_t_ -#define _Inout_tz_cap_(size) _Pre_tz_cap_(size) _Post_tz_ -#define _Inout_opt_tz_cap_(size) _Pre_opt_tz_cap_(size) _Post_tz_ -#define _Inout_tz_bytecap_(size) _Pre_tz_bytecap_(size) _Post_tz_ -#define _Inout_opt_tz_bytecap_(size) _Pre_opt_tz_bytecap_(size) _Post_tz_ +#define _Inout_t_cap_(size) _Pre_t_cap_(size) _Post_t_ +#define _Inout_opt_t_cap_(size) _Pre_opt_t_cap_(size) _Post_t_ +#define _Inout_t_bytecap_(size) _Pre_t_bytecap_(size) _Post_t_ +#define _Inout_opt_t_bytecap_(size) _Pre_opt_t_bytecap_(size) _Post_t_ +#define _Inout_tz_cap_(size) _Pre_tz_cap_(size) _Post_tz_ +#define _Inout_opt_tz_cap_(size) _Pre_opt_tz_cap_(size) _Post_tz_ +#define _Inout_tz_bytecap_(size) _Pre_tz_bytecap_(size) _Post_tz_ +#define _Inout_opt_tz_bytecap_(size) _Pre_opt_tz_bytecap_(size) _Post_tz_ -#define _Inout_t_cap_c_(size) _Pre_t_cap_c_(size) _Post_t_ -#define _Inout_opt_t_cap_c_(size) _Pre_opt_t_cap_c_(size) _Post_t_ -#define _Inout_t_bytecap_c_(size) _Pre_t_bytecap_c_(size) _Post_t_ -#define _Inout_opt_t_bytecap_c_(size) _Pre_opt_t_bytecap_c_(size) _Post_t_ -#define _Inout_tz_cap_c_(size) _Pre_tz_cap_c_(size) _Post_tz_ -#define _Inout_opt_tz_cap_c_(size) _Pre_opt_tz_cap_c_(size) _Post_tz_ -#define _Inout_tz_bytecap_c_(size) _Pre_tz_bytecap_c_(size) _Post_tz_ -#define _Inout_opt_tz_bytecap_c_(size) _Pre_opt_tz_bytecap_c_(size) _Post_tz_ +#define _Inout_t_cap_c_(size) _Pre_t_cap_c_(size) _Post_t_ +#define _Inout_opt_t_cap_c_(size) _Pre_opt_t_cap_c_(size) _Post_t_ +#define _Inout_t_bytecap_c_(size) _Pre_t_bytecap_c_(size) _Post_t_ +#define _Inout_opt_t_bytecap_c_(size) _Pre_opt_t_bytecap_c_(size) _Post_t_ +#define _Inout_tz_cap_c_(size) _Pre_tz_cap_c_(size) _Post_tz_ +#define _Inout_opt_tz_cap_c_(size) _Pre_opt_tz_cap_c_(size) _Post_tz_ +#define _Inout_tz_bytecap_c_(size) _Pre_tz_bytecap_c_(size) _Post_tz_ +#define _Inout_opt_tz_bytecap_c_(size) _Pre_opt_tz_bytecap_c_(size) _Post_tz_ -#define _Inout_t_cap_x_(size) _Pre_t_cap_x_(size) _Post_t_ -#define _Inout_opt_t_cap_x_(size) _Pre_opt_t_cap_x_(size) _Post_t_ -#define _Inout_t_bytecap_x_(size) _Pre_t_bytecap_x_(size) _Post_t_ -#define _Inout_opt_t_bytecap_x_(size) _Pre_opt_t_bytecap_x_(size) _Post_t_ -#define _Inout_tz_cap_x_(size) _Pre_tz_cap_x_(size) _Post_tz_ -#define _Inout_opt_tz_cap_x_(size) _Pre_opt_tz_cap_x_(size) _Post_tz_ -#define _Inout_tz_bytecap_x_(size) _Pre_tz_bytecap_x_(size) _Post_tz_ -#define _Inout_opt_tz_bytecap_x_(size) _Pre_opt_tz_bytecap_x_(size) _Post_tz_ +#define _Inout_t_cap_x_(size) _Pre_t_cap_x_(size) _Post_t_ +#define _Inout_opt_t_cap_x_(size) _Pre_opt_t_cap_x_(size) _Post_t_ +#define _Inout_t_bytecap_x_(size) _Pre_t_bytecap_x_(size) _Post_t_ +#define _Inout_opt_t_bytecap_x_(size) _Pre_opt_t_bytecap_x_(size) _Post_t_ +#define _Inout_tz_cap_x_(size) _Pre_tz_cap_x_(size) _Post_tz_ +#define _Inout_opt_tz_cap_x_(size) _Pre_opt_tz_cap_x_(size) _Post_tz_ +#define _Inout_tz_bytecap_x_(size) _Pre_tz_bytecap_x_(size) _Post_tz_ +#define _Inout_opt_tz_bytecap_x_(size) _Pre_opt_tz_bytecap_x_(size) _Post_tz_ -#define _Ret_t_ _Ret2_impl_(__notnull_impl, __count_x_impl([0])) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTStr) -#define _Ret_opt_t_ _Ret2_impl_(__maybenull_impl,__count_x_impl([0])) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTStr) -#define _Ret_tz_ _Ret2_impl_(__notnull_impl, __zterm_impl) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTZStr) -#define _Ret_opt_tz_ _Ret2_impl_(__maybenull_impl,__zterm_impl) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTZStr) +#define _Ret_t_ _Ret2_impl_(__notnull_impl, __count_x_impl([0])) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTStr) +#define _Ret_opt_t_ _Ret2_impl_(__maybenull_impl, __count_x_impl([0])) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTStr) +#define _Ret_tz_ _Ret2_impl_(__notnull_impl, __zterm_impl) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTZStr) +#define _Ret_opt_tz_ _Ret2_impl_(__maybenull_impl, __zterm_impl) _Ret_valid_impl_ _$RET_STR_TYPE(_$postTZStr) -#define _Pre_t_ _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__count_x_impl([0])) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_ _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__count_x_impl([0])) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_tz_ _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_ _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_t_ \ + _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__count_x_impl([0])) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_ \ + _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__count_x_impl([0])) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_tz_ _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_ \ + _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_t_cap_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__cap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_cap_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__cap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_t_bytecap_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__bytecap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_bytecap_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__bytecap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_tz_cap_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_cap_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_tz_bytecap_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_bytecap_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_t_cap_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __cap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_cap_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __cap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_t_bytecap_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __bytecap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_bytecap_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __bytecap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_tz_cap_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl, __cap_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_cap_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl, __cap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_tz_bytecap_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl, __bytecap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_bytecap_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl, __bytecap_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_t_cap_c_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__cap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_cap_c_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__cap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_t_bytecap_c_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__bytecap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_bytecap_c_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__bytecap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_tz_cap_c_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_cap_c_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_tz_bytecap_c_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_bytecap_c_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_t_cap_c_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __cap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_cap_c_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __cap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_t_bytecap_c_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_bytecap_c_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_tz_cap_c_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl, __cap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_cap_c_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl, __cap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_tz_bytecap_c_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl, __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_bytecap_c_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl, __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_t_cap_x_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__cap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_cap_x_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__cap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_t_bytecap_x_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__bytecap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_opt_t_bytecap_x_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]),__bytecap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTStr) -#define _Pre_tz_cap_x_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_x_impl(_csize)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_cap_x_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_tz_bytecap_x_(size) _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Pre_opt_tz_bytecap_x_(size) _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_t_cap_x_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __cap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_cap_x_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __cap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_t_bytecap_x_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_opt_t_bytecap_x_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__count_x_impl([0]), __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTStr) +#define _Pre_tz_cap_x_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl, __cap_x_impl(_csize)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_cap_x_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl, __cap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_tz_bytecap_x_(size) \ + _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl, __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) +#define _Pre_opt_tz_bytecap_x_(size) \ + _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl, __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$STR_TYPE(_$preTZStr) -#define _Post_t_ _Post1_impl_(__count_x_impl([0])) _Post_valid_impl_ _$STR_TYPE(_$postTStr) -#define _Post_tz_ _Post1_impl_(__zterm_impl) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_t_ _Post1_impl_(__count_x_impl([0])) _Post_valid_impl_ _$STR_TYPE(_$postTStr) +#define _Post_tz_ _Post1_impl_(__zterm_impl) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -// _Post_t_count family not possible, conflicting WritableElements property +// _Post_t_count family not possible, conflicting WritableElements property -#define _Post_tz_count_(size) _Post2_impl_(__zterm_impl,__count_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -#define _Post_tz_bytecount_(size) _Post2_impl_(__zterm_impl,__bytecount_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -#define _Post_tz_count_c_(size) _Post2_impl_(__zterm_impl,__count_c_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -#define _Post_tz_bytecount_c_(size) _Post2_impl_(__zterm_impl,__bytecount_c_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -#define _Post_tz_count_x_(size) _Post2_impl_(__zterm_impl,__count_x_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -#define _Post_tz_bytecount_x_(size) _Post2_impl_(__zterm_impl,__bytecount_impl_x(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_tz_count_(size) _Post2_impl_(__zterm_impl, __count_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_tz_bytecount_(size) \ + _Post2_impl_(__zterm_impl, __bytecount_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_tz_count_c_(size) \ + _Post2_impl_(__zterm_impl, __count_c_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_tz_bytecount_c_(size) \ + _Post2_impl_(__zterm_impl, __bytecount_c_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_tz_count_x_(size) \ + _Post2_impl_(__zterm_impl, __count_x_impl(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) +#define _Post_tz_bytecount_x_(size) \ + _Post2_impl_(__zterm_impl, __bytecount_impl_x(size)) _Post_valid_impl_ _$STR_TYPE(_$postTZStr) -#define _Deref_out_t_ _Out_ _Deref_post_t_ -#define _Deref_out_opt_t_ _Out_ _Deref_post_opt_t_ -#define _Deref_out_tz_ _Out_ _Deref_post_tz_ -#define _Deref_out_opt_tz_ _Out_ _Deref_post_opt_tz_ +#define _Deref_out_t_ _Out_ _Deref_post_t_ +#define _Deref_out_opt_t_ _Out_ _Deref_post_opt_t_ +#define _Deref_out_tz_ _Out_ _Deref_post_tz_ +#define _Deref_out_opt_tz_ _Out_ _Deref_post_opt_tz_ -#define _Deref_pre_t_ _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__count_x_impl([0])) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_ _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__count_x_impl([0])) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_tz_ _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_ _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_t_ \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__count_x_impl([0])) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_ \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__count_x_impl([0])) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_tz_ \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__zterm_impl) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_ \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__zterm_impl) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_t_cap_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__cap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_cap_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__cap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_t_bytecap_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__bytecap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_bytecap_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__bytecap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_tz_cap_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_cap_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_tz_bytecap_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_bytecap_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_t_cap_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __cap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_cap_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __cap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_t_bytecap_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __bytecap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_bytecap_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __bytecap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_tz_cap_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __cap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_cap_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __cap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_tz_bytecap_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __bytecap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_bytecap_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __bytecap_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_t_cap_c_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__cap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_cap_c_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__cap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_t_bytecap_c_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__bytecap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_bytecap_c_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__bytecap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_tz_cap_c_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_cap_c_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_tz_bytecap_c_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_bytecap_c_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_t_cap_c_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __cap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_cap_c_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __cap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_t_bytecap_c_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_bytecap_c_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_tz_cap_c_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __cap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_cap_c_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __cap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_tz_bytecap_c_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_bytecap_c_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __bytecap_c_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_t_cap_x_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__cap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_cap_x_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__cap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_t_bytecap_x_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__bytecap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_opt_t_bytecap_x_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]),__bytecap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) -#define _Deref_pre_tz_cap_x_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_cap_x_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_tz_bytecap_x_(size) _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_pre_opt_tz_bytecap_x_(size) _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_t_cap_x_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __cap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_cap_x_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __cap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_t_bytecap_x_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_opt_t_bytecap_x_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__count_x_impl([0]), __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTStr) +#define _Deref_pre_tz_cap_x_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __cap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_cap_x_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __cap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_tz_bytecap_x_(size) \ + _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) +#define _Deref_pre_opt_tz_bytecap_x_(size) \ + _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl, __bytecap_x_impl(size)) \ + _Pre_valid_impl_ _$DEREF_STR_TYPE(_$preTZStr) -#define _Deref_post_t_ _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__count_x_impl([0])) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_ _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__count_x_impl([0])) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_tz_ _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__zterm_impl) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) -#define _Deref_post_opt_tz_ _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__zterm_impl) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) +#define _Deref_post_t_ \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__count_x_impl([0])) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_ \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__count_x_impl([0])) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_tz_ \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__zterm_impl) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) +#define _Deref_post_opt_tz_ \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__zterm_impl) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) -#define _Deref_post_t_cap_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__cap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_cap_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__cap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_t_bytecap_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__bytecap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_bytecap_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__bytecap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_t_cap_(size) \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __cap_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_cap_(size) \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __cap_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_t_bytecap_(size) \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __bytecap_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_bytecap_(size) \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __bytecap_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) #define _Deref_post_tz_cap_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl),__cap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_opt_tz_cap_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl),__cap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_tz_bytecap_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl),__bytecap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_opt_tz_bytecap_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl),__bytecap_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) -#define _Deref_post_t_cap_c_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__cap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_cap_c_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__cap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_t_bytecap_c_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__bytecap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_bytecap_c_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__bytecap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_t_cap_c_(size) \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __cap_c_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_cap_c_(size) \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __cap_c_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_t_bytecap_c_(size) \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __bytecap_c_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_bytecap_c_(size) \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __bytecap_c_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) #define _Deref_post_tz_cap_c_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl),__cap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_opt_tz_cap_c_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl),__cap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_tz_bytecap_c_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl),__bytecap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_opt_tz_bytecap_c_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl),__bytecap_c_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) -#define _Deref_post_t_cap_x_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__cap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_cap_x_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__cap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_t_bytecap_x_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__bytecap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) -#define _Deref_post_opt_t_bytecap_x_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]),__bytecap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_t_cap_x_(size) \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __cap_x_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_cap_x_(size) \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __cap_x_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_t_bytecap_x_(size) \ + _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __bytecap_x_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) +#define _Deref_post_opt_t_bytecap_x_(size) \ + _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__count_x_impl([0]), __bytecap_x_impl(size)) \ + _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTStr) #define _Deref_post_tz_cap_x_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl),__cap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_opt_tz_cap_x_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl),__cap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_tz_bytecap_x_(size) _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl),__bytecap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) #define _Deref_post_opt_tz_bytecap_x_(size) _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl),__bytecap_x_impl(size)) _Post_valid_impl_ _$DEREF_STR_TYPE(_$postTZStr) -#define _Prepost_t_ _Pre_t_ _Post_t_ -#define _Prepost_opt_t_ _Pre_opt_t_ _Post_t_ -#define _Prepost_tz_ _Pre_tz_ _Post_tz_ -#define _Prepost_opt_tz_ _Pre_opt_tz_ _Post_tz_ +#define _Prepost_t_ _Pre_t_ _Post_t_ +#define _Prepost_opt_t_ _Pre_opt_t_ _Post_t_ +#define _Prepost_tz_ _Pre_tz_ _Post_tz_ +#define _Prepost_opt_tz_ _Pre_opt_tz_ _Post_tz_ -#define _Deref_prepost_t_ _Deref_pre_t_ _Deref_post_t_ -#define _Deref_prepost_opt_t_ _Deref_pre_opt_t_ _Deref_post_opt_t_ -#define _Deref_prepost_tz_ _Deref_pre_tz_ _Deref_post_tz_ -#define _Deref_prepost_opt_tz_ _Deref_pre_opt_tz_ _Deref_post_opt_tz_ +#define _Deref_prepost_t_ _Deref_pre_t_ _Deref_post_t_ +#define _Deref_prepost_opt_t_ _Deref_pre_opt_t_ _Deref_post_opt_t_ +#define _Deref_prepost_tz_ _Deref_pre_tz_ _Deref_post_tz_ +#define _Deref_prepost_opt_tz_ _Deref_pre_opt_tz_ _Deref_post_opt_tz_ // These are stronger than the related _opt_ annotations, in that the buffer pointer must be non-null if and only if // the associated count parameter is non-zero. For example: @@ -243,9 +385,11 @@ // // Read( rgBooks, 0 ); // -#define _In_reads_or_null_if_zero_(size) _In_reads_(size) _When_(0 == size, _Pre_null_) _When_(0 < size, _Pre_notnull_) -#define _Out_writes_or_null_if_zero_(size) _Out_writes_(size) _When_(0 == size, _Pre_null_) _When_(0 < size, _Pre_notnull_) -#define _Inout_updates_or_null_if_zero_(size) _Inout_updates_(size) _When_(0 == size, _Pre_null_) _When_(0 < size, _Pre_notnull_) +#define _In_reads_or_null_if_zero_(size) _In_reads_(size) _When_(0 == size, _Pre_null_) _When_(0 < size, _Pre_notnull_) +#define _Out_writes_or_null_if_zero_(size) \ + _Out_writes_(size) _When_(0 == size, _Pre_null_) _When_(0 < size, _Pre_notnull_) +#define _Inout_updates_or_null_if_zero_(size) \ + _Inout_updates_(size) _When_(0 == size, _Pre_null_) _When_(0 < size, _Pre_notnull_) #define _$STR_TYPE(type) #define _$RET_STR_TYPE(type) @@ -264,5 +408,5 @@ #endif #if !defined(OACR_CAPTURE_FIXUP) -#define OACR_CAPTURE_FIXUP(tag,match,replace) _SA_annotes3(SAL_OACRCapture, tag_FIXUP, match, replace) +#define OACR_CAPTURE_FIXUP(tag, match, replace) _SA_annotes3(SAL_OACRCapture, tag_FIXUP, match, replace) #endif diff --git a/libs/oacr_posix/include/sal.h b/libs/oacr_posix/include/sal.h index 15e02c2..d6936af 100644 --- a/libs/oacr_posix/include/sal.h +++ b/libs/oacr_posix/include/sal.h @@ -26,7 +26,7 @@ #define _Ret_z_ #define _Ret_maybenull_ #define _Ret_notnull_ -#define _Ret_range_(x,y) +#define _Ret_range_(x, y) #define _Post_writable_byte_size_(x) #define _Deref_pre_valid_ #define _Deref_post_valid_ @@ -35,7 +35,7 @@ #define _Printf_format_string_ #define _Use_decl_annotations_ #define _Null_terminated_ -#define _Out_cap_post_count_(x,y) +#define _Out_cap_post_count_(x, y) #define _Out_cap_(x) #define UNREFERENCED_PARAMETER(x) #define _In_reads_bytes_(x) diff --git a/libs/object/include/object/fixedSwarm.h b/libs/object/include/object/fixedSwarm.h index 2b5f4fb..2b70949 100644 --- a/libs/object/include/object/fixedSwarm.h +++ b/libs/object/include/object/fixedSwarm.h @@ -24,7 +24,8 @@ share the same reference counter. // // Mso::FixedSwarmBase does only one memory allocation for all objects in the swarm. // It is very compact: on 64 bit platform the size is 16 bytes for ObjectWeakRef -// (8 bytes v-table + 4 bytes ref count + 4 bytes weak ref count) and one pointer for each swarm member to point to the ObjectWeakRef. +// (8 bytes v-table + 4 bytes ref count + 4 bytes weak ref count) and one pointer for each swarm member to point to the +// ObjectWeakRef. // // To create an Mso::FixedSwarmBase use Mso::Make method.. // To create a swarm member call MakeMember() instance methods. @@ -40,7 +41,7 @@ namespace Mso { namespace Details { /** - Storage for FixedSwarmBase class. In some sense this is a specialized std::tuple. + Storage for FixedSwarmBase class. In some sense this is a specialized std::tuple. */ template struct FixedSwarmStorage; @@ -48,39 +49,39 @@ struct FixedSwarmStorage; template <> struct FixedSwarmStorage<> { - void DestroyObject() const noexcept - { - // Do nothing because there is no storage in this class - UNREFERENCED_OACR(this); - } + void DestroyObject() const noexcept + { + // Do nothing because there is no storage in this class + UNREFERENCED_OACR(this); + } }; template struct FixedSwarmStorage : public FixedSwarmStorage { - using Super = FixedSwarmStorage; + using Super = FixedSwarmStorage; - FixedSwarmStorage() noexcept - { - Mso::Details::SetWeakRef(&m_memberStorage, nullptr); - } + FixedSwarmStorage() noexcept + { + Mso::Details::SetWeakRef(&m_memberStorage, nullptr); + } - void DestroyObject() const noexcept - { - if (Mso::Details::GetWeakRef(&m_memberStorage)) - { - T0::RefCountPolicy::Deleter::template Delete(static_cast((void*) &m_memberStorage)); - } + void DestroyObject() const noexcept + { + if (Mso::Details::GetWeakRef(&m_memberStorage)) + { + T0::RefCountPolicy::Deleter::template Delete(static_cast((void*)&m_memberStorage)); + } - Super::DestroyObject(); - } + Super::DestroyObject(); + } - ObjectWeakRef* m_weakRefPlaceholder; // reserves negative space before m_memberStorage. - typename std::aligned_storage::value>::type m_memberStorage; + ObjectWeakRef* m_weakRefPlaceholder; // reserves negative space before m_memberStorage. + typename std::aligned_storage::value>::type m_memberStorage; }; /** - A helper type to access FixedSwarmStorage member by index similar to std::tuple. + A helper type to access FixedSwarmStorage member by index similar to std::tuple. */ template struct FixedSwarmStorageMember; @@ -88,13 +89,13 @@ struct FixedSwarmStorageMember; template struct FixedSwarmStorageMember<0, FixedSwarmStorage> { - using Type = T; - using StorageType = FixedSwarmStorage; + using Type = T; + using StorageType = FixedSwarmStorage; }; template struct FixedSwarmStorageMember> - : public FixedSwarmStorageMember> + : public FixedSwarmStorageMember> { }; @@ -103,123 +104,123 @@ struct FixedSwarmStorageMember> template struct FixedSwarmMemberMemoryGuard { - using Type = T; + using Type = T; - ~FixedSwarmMemberMemoryGuard() noexcept - { - if (ObjMemory) - { - Container->ReleaseWeakRef(); - Mso::Details::SetWeakRef(ObjMemory, nullptr); - } - else if (Obj) - { - // Initialize method failed. - T::RefCountPolicy::Deleter::template Delete(static_cast(Obj)); - Mso::Details::SetWeakRef(Obj, nullptr); - } - } + ~FixedSwarmMemberMemoryGuard() noexcept + { + if (ObjMemory) + { + Container->ReleaseWeakRef(); + Mso::Details::SetWeakRef(ObjMemory, nullptr); + } + else if (Obj) + { + // Initialize method failed. + T::RefCountPolicy::Deleter::template Delete(static_cast(Obj)); + Mso::Details::SetWeakRef(Obj, nullptr); + } + } public: // We use a public fields to reduce number of generated methods. - // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates incorrect code for ship builds. - void* ObjMemory; - T* Obj; - TContainer* Container; + // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates + // incorrect code for ship builds. + void* ObjMemory; + T* Obj; + TContainer* Container; }; /** - FixedSwarmBase is a fixed size swarm which knows all its member type at the creation. - It is like an std::tuple. - By knowing all types upfront we can make the most compact representation of the swarm, and be very flexible about - swarm member types because we know their type in swarm. - Members can be IUnknown, IRefCounted, or object without v-table with AddRef() and Release() methods. - The only requirement is that the members must support the weak ref count where pointer to ObjectWeakRef is in - the nearest negative offset from the object. - When FixedSwarmBase ref count goes to zero it destroys all objects in the Swarm. + FixedSwarmBase is a fixed size swarm which knows all its member type at the creation. + It is like an std::tuple. + By knowing all types upfront we can make the most compact representation of the swarm, and be very flexible about + swarm member types because we know their type in swarm. + Members can be IUnknown, IRefCounted, or object without v-table with AddRef() and Release() methods. + The only requirement is that the members must support the weak ref count where pointer to ObjectWeakRef is in + the nearest negative offset from the object. + When FixedSwarmBase ref count goes to zero it destroys all objects in the Swarm. */ template -class FixedSwarmBase - : public TBase +class FixedSwarmBase : public TBase { - static_assert(std::is_base_of::value, "TBase must be inherited from ObjectWeakRef."); + static_assert(std::is_base_of::value, "TBase must be inherited from ObjectWeakRef."); - using Super = TBase; - using StorageType = Details::FixedSwarmStorage; - template using MemberType = typename Details::FixedSwarmStorageMember::Type; - template using MemberStorageType = typename Details::FixedSwarmStorageMember::StorageType; + using Super = TBase; + using StorageType = Details::FixedSwarmStorage; + template + using MemberType = typename Details::FixedSwarmStorageMember::Type; + template + using MemberStorageType = typename Details::FixedSwarmStorageMember::StorageType; public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; - FixedSwarmBase() noexcept - : Super() - , m_storage() - { - } + FixedSwarmBase() noexcept : Super(), m_storage() {} - DECLARE_COPYCONSTR_AND_ASSIGNMENT(FixedSwarmBase); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(FixedSwarmBase); - template - MemberType* Get() const noexcept - { - void* item = &static_cast*>(const_cast(&m_storage))->m_memberStorage; - if (Mso::Details::GetWeakRef(item)) - { - return static_cast*>(item); - } + template + MemberType* Get() const noexcept + { + void* item = &static_cast*>(const_cast(&m_storage))->m_memberStorage; + if (Mso::Details::GetWeakRef(item)) + { + return static_cast*>(item); + } - return nullptr; - } + return nullptr; + } - template > - Mso::WeakPtr GetWeakPtr() const noexcept - { - Mso::WeakPtr result; + template > + Mso::WeakPtr GetWeakPtr() const noexcept + { + Mso::WeakPtr result; - void* member = &static_cast*>(const_cast(&m_storage))->m_memberStorage; - if (Mso::Details::GetWeakRef(member)) - { - result = Mso::WeakPtr(reinterpret_cast*>(member), const_cast(static_cast(this))); - } + void* member = &static_cast*>(const_cast(&m_storage))->m_memberStorage; + if (Mso::Details::GetWeakRef(member)) + { + result = Mso::WeakPtr( + reinterpret_cast*>(member), + const_cast(static_cast(this))); + } - return result; - } + return result; + } - template - void MakeMember(TArgs&&... args) noexcept(MemberType::MakePolicy::IsNoExcept) - { - using TMember = MemberType; + template + void MakeMember(TArgs&&... args) noexcept(MemberType::MakePolicy::IsNoExcept) + { + using TMember = MemberType; - void* memberMemory = &static_cast*>(const_cast(&m_storage))->m_memberStorage; + void* memberMemory = &static_cast*>(const_cast(&m_storage))->m_memberStorage; - // Initialize weak reference for the member - Mso::Details::SetWeakRef(memberMemory, this); - Super::AddWeakRef(); // To match ReleaseWeakRef() call in member destructor. + // Initialize weak reference for the member + Mso::Details::SetWeakRef(memberMemory, this); + Super::AddWeakRef(); // To match ReleaseWeakRef() call in member destructor. - FixedSwarmMemberMemoryGuard memoryGuard = { memberMemory, nullptr, this }; - TMember::MakePolicy::template Make(memoryGuard, std::forward(args)...); + FixedSwarmMemberMemoryGuard memoryGuard = {memberMemory, nullptr, this}; + TMember::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(TMember::RefCountPolicy::ValidateObject(memoryGuard)); - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - } + Debug(TMember::RefCountPolicy::ValidateObject(memoryGuard)); + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + } protected: - using FixedSwarmType = FixedSwarmBase; + using FixedSwarmType = FixedSwarmBase; - virtual void DestroyObject() noexcept override - { - m_storage.DestroyObject(); - Super::ReleaseWeakRef(); - } + virtual void DestroyObject() noexcept override + { + m_storage.DestroyObject(); + Super::ReleaseWeakRef(); + } - virtual void DestroyContainer() const noexcept override - { - this->~FixedSwarmBase(); - Super::RefCountPolicy::Allocator::Deallocate(const_cast(this)); - } + virtual void DestroyContainer() const noexcept override + { + this->~FixedSwarmBase(); + Super::RefCountPolicy::Allocator::Deallocate(const_cast(this)); + } private: - StorageType m_storage; + StorageType m_storage; }; template diff --git a/libs/object/include/object/lazyInit.h b/libs/object/include/object/lazyInit.h index 81d610a..44b7846 100644 --- a/libs/object/include/object/lazyInit.h +++ b/libs/object/include/object/lazyInit.h @@ -35,63 +35,64 @@ namespace Mso { namespace Object { template class LazyInit final { - static_assert(std::is_base_of::value || std::is_base_of::value, - "The type must be derived from Mso::IRefCounted or IUnknown."); + static_assert( + std::is_base_of::value || std::is_base_of::value, + "The type must be derived from Mso::IRefCounted or IUnknown."); public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(LazyInit); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(LazyInit); - explicit LazyInit() noexcept = default; + explicit LazyInit() noexcept = default; - ~LazyInit() noexcept - { - Release(); - } + ~LazyInit() noexcept + { + Release(); + } - template - TInterface& Get(TArgs&&... args) noexcept - { - bool unused{ false }; - return Get(unused, std::forward(args)...); - } + template + TInterface& Get(TArgs&&... args) noexcept + { + bool unused{false}; + return Get(unused, std::forward(args)...); + } - template - TInterface& Get(bool& created, TArgs&&... args) noexcept - { - created = false; - auto instance{ m_instance.load(std::memory_order_acquire) }; - if (!instance) - { - auto newInstance{ Mso::Make(std::forward(args)...) }; - if (m_instance.compare_exchange_strong(instance, newInstance.Get())) - { - // The current thread won the race. - // Ensure that a pointer with a reference count of 1 is stored. - instance = newInstance.Detach(); - created = true; - } - } + template + TInterface& Get(bool& created, TArgs&&... args) noexcept + { + created = false; + auto instance{m_instance.load(std::memory_order_acquire)}; + if (!instance) + { + auto newInstance{Mso::Make(std::forward(args)...)}; + if (m_instance.compare_exchange_strong(instance, newInstance.Get())) + { + // The current thread won the race. + // Ensure that a pointer with a reference count of 1 is stored. + instance = newInstance.Detach(); + created = true; + } + } - return *instance; - } + return *instance; + } - bool IsInitialized() const noexcept - { - return m_instance.load(std::memory_order_acquire) != nullptr; - } + bool IsInitialized() const noexcept + { + return m_instance.load(std::memory_order_acquire) != nullptr; + } - void Release() noexcept - { - auto instance{ m_instance.exchange(nullptr) }; - if (instance) - { - // Release the reference count added in Create(). - instance->Release(); - } - } + void Release() noexcept + { + auto instance{m_instance.exchange(nullptr)}; + if (instance) + { + // Release the reference count added in Create(). + instance->Release(); + } + } private: - std::atomic m_instance{ nullptr }; + std::atomic m_instance{nullptr}; }; }} // namespace Mso::Object \ No newline at end of file diff --git a/libs/object/include/object/make.h b/libs/object/include/object/make.h index fe2bfe0..fbe4fa2 100644 --- a/libs/object/include/object/make.h +++ b/libs/object/include/object/make.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Support for reference counting. + Support for reference counting. */ #pragma once @@ -20,128 +20,127 @@ namespace Mso { /** - Mso::Make creates a new instance of class T and returns a TCntPtr to the instance of type TResult. - TResult is either the original type T (default), or one of its interfaces. - Returning an interface type can help to avoid creation of unnecessary TCntPtr template instances. + Mso::Make creates a new instance of class T and returns a TCntPtr to the instance of type TResult. + TResult is either the original type T (default), or one of its interfaces. + Returning an interface type can help to avoid creation of unnecessary TCntPtr template instances. - Method Make is noexcept depending on the Make policy IsNoExcept value. + Method Make is noexcept depending on the Make policy IsNoExcept value. */ template inline Mso::TCntPtr Make(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) { - typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard); - VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x01117748 /* tag_bex3i */); + typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard); + VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x01117748 /* tag_bex3i */); - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return Mso::TCntPtr(result, /*fDoAddRef:*/ false); + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return Mso::TCntPtr(result, /*fDoAddRef:*/ false); } /** - Mso::MakeAlloc is an Mso::Make method for types T that use allocators accepting an argument. - The allocator argument allows to implement stateful allocators. + Mso::MakeAlloc is an Mso::Make method for types T that use allocators accepting an argument. + The allocator argument allows to implement stateful allocators. - MakeAlloc creates a new instance of class T and returns a TCntPtr to the instance of type TResult. - TResult is either the original type T (default), or one of its interfaces. - Returning an interface type can help to avoid creation of unnecessary TCntPtr template instantiations. + MakeAlloc creates a new instance of class T and returns a TCntPtr to the instance of type TResult. + TResult is either the original type T (default), or one of its interfaces. + Returning an interface type can help to avoid creation of unnecessary TCntPtr template instantiations. - Method MakeAlloc is noexcept depending on the Make policy IsNoExcept value. + Method MakeAlloc is noexcept depending on the Make policy IsNoExcept value. */ template inline Mso::TCntPtr MakeAlloc(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) { - typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); - VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x01117749 /* tag_bex3j */); + typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); + VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x01117749 /* tag_bex3j */); - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return Mso::TCntPtr(result, /*fDoAddRef:*/ false); + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return Mso::TCntPtr(result, /*fDoAddRef:*/ false); } /** - Mso::MakeElseNull creates a new instance of class T and returns a TCntPtr to the instance of type TResult. - If memory cannot be allocated then it returns nullptr. + Mso::MakeElseNull creates a new instance of class T and returns a TCntPtr to the instance of type TResult. + If memory cannot be allocated then it returns nullptr. - TResult is either the original type T (default), or one of its interfaces. - Returning an interface type can help to avoid creation of unnecessary TCntPtr template instances. + TResult is either the original type T (default), or one of its interfaces. + Returning an interface type can help to avoid creation of unnecessary TCntPtr template instances. - Method MakeElseNull is noexcept depending on the Make policy IsNoExcept value. + Method MakeElseNull is noexcept depending on the Make policy IsNoExcept value. */ template inline Mso::TCntPtr MakeElseNull(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) { - Mso::TCntPtr result; // Hopefully we can benefit from NRVO + Mso::TCntPtr result; // Hopefully we can benefit from NRVO - typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard); - if (memoryGuard.ObjMemory) - { - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard); + if (memoryGuard.ObjMemory) + { + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - result = Mso::TCntPtr(memoryGuard.Obj, /*fDoAddRef:*/ false); - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - } + result = Mso::TCntPtr(memoryGuard.Obj, /*fDoAddRef:*/ false); + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + } - return result; + return result; } /** - Mso::MakeAllocElseNull is an Mso::MakeElseNull method for types T that use allocators accepting an argument. - The allocator argument allows to implement stateful allocators. - If memory cannot be allocated then it returns nullptr. + Mso::MakeAllocElseNull is an Mso::MakeElseNull method for types T that use allocators accepting an argument. + The allocator argument allows to implement stateful allocators. + If memory cannot be allocated then it returns nullptr. - MakeAllocElseNull creates a new instance of class T and returns a TCntPtr to the instance of type TResult. - TResult is either the original type T (default), or one of its interfaces. - Returning an interface type can help to avoid creation of unnecessary TCntPtr template instantiations. + MakeAllocElseNull creates a new instance of class T and returns a TCntPtr to the instance of type TResult. + TResult is either the original type T (default), or one of its interfaces. + Returning an interface type can help to avoid creation of unnecessary TCntPtr template instantiations. - Method MakeAllocElseNull is noexcept depending on the Make policy IsNoExcept value. + Method MakeAllocElseNull is noexcept depending on the Make policy IsNoExcept value. */ template -inline Mso::TCntPtr MakeAllocElseNull(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) +inline Mso::TCntPtr MakeAllocElseNull(TAllocArg&& allocArg, TArgs&&... args) noexcept( + T::MakePolicy::IsNoExcept) { - Mso::TCntPtr result; // Hopefully we can benefit from NRVO + Mso::TCntPtr result; // Hopefully we can benefit from NRVO - typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); - if (memoryGuard.ObjMemory) - { - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); + if (memoryGuard.ObjMemory) + { + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - result = Mso::TCntPtr(memoryGuard.Obj, /*fDoAddRef:*/ false); - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - } + result = Mso::TCntPtr(memoryGuard.Obj, /*fDoAddRef:*/ false); + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + } - return result; + return result; } - // Make policy defines how an instance is created in the pre-allocated memory. -namespace MakePolicy -{ +namespace MakePolicy { /// ThrowCtor MakePolicy passes all parameters to the constructor. /// ThrowCtor::Make may throw an exception if constructor throws. /// To allow this class to access private constructor add "friend MakePolicy;" to your class. struct ThrowCtor { - static const bool IsNoExcept = false; + static const bool IsNoExcept = false; - template - static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) - { - OACR_POSSIBLE_THROW; - memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(std::forward(args)...); - memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. - } + template + static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) + { + OACR_POSSIBLE_THROW; + memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(std::forward(args)...); + memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. + } }; /// NoThrowCtor MakePolicy passes all parameters to the constructor. @@ -149,66 +148,66 @@ struct ThrowCtor /// To allow this class to access private constructor add "friend MakePolicy;" to your class. struct NoThrowCtor { - static const bool IsNoExcept = true; + static const bool IsNoExcept = true; - template - static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) noexcept - { - memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(std::forward(args)...); - memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. - } + template + static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) noexcept + { + memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(std::forward(args)...); + memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. + } }; -/// ThrowCtorAndInitializeThis MakePolicy calls default constructor and then passes all parameters to InitializeThis method. -/// ThrowCtor::Make may throw an exception if constructor or InitializeThis throw. -/// To allow this class to access private constructor add "friend MakePolicy;" to your class. +/// ThrowCtorAndInitializeThis MakePolicy calls default constructor and then passes all parameters to InitializeThis +/// method. ThrowCtor::Make may throw an exception if constructor or InitializeThis throw. To allow this class to access +/// private constructor add "friend MakePolicy;" to your class. struct ThrowCtorAndInitializeThis { - static const bool IsNoExcept = false; + static const bool IsNoExcept = false; - template - static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) - { - OACR_POSSIBLE_THROW; - memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(); - memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. - memoryGuard.Obj->InitializeThis(std::forward(args)...); - } + template + static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) + { + OACR_POSSIBLE_THROW; + memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(); + memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. + memoryGuard.Obj->InitializeThis(std::forward(args)...); + } }; -/// NoThrowCtorAndInitializeThis MakePolicy calls default constructor and then passes all parameters to InitializeThis method. -/// NoThrowCtor::Make does not throw exception and crashes the app if constructor or InitializeThis throw. -/// To allow this class to access private constructor add "friend MakePolicy;" to your class. +/// NoThrowCtorAndInitializeThis MakePolicy calls default constructor and then passes all parameters to InitializeThis +/// method. NoThrowCtor::Make does not throw exception and crashes the app if constructor or InitializeThis throw. To +/// allow this class to access private constructor add "friend MakePolicy;" to your class. struct NoThrowCtorAndInitializeThis { - static const bool IsNoExcept = true; + static const bool IsNoExcept = true; - template - static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) noexcept - { - memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(); - memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. - memoryGuard.Obj->InitializeThis(std::forward(args)...); - } + template + static void Make(TMemoryGuard& memoryGuard, TArgs&&... args) noexcept + { + memoryGuard.Obj = ::new (memoryGuard.ObjMemory) T(); + memoryGuard.ObjMemory = nullptr; // Memory is now controlled by the object. Set to null to avoid memory destruction. + memoryGuard.Obj->InitializeThis(std::forward(args)...); + } }; } // namespace MakePolicy /** - Default memory allocator for ref counted objects. + Default memory allocator for ref counted objects. */ struct MakeAllocator { - static void* Allocate(size_t size) noexcept - { - Debug(Mso::Memory::AutoIgnoreLeakScope lazy); - return Mso::Memory::AllocateEx(size, Mso::Memory::AllocFlags::ShutdownLeak); - } + static void* Allocate(size_t size) noexcept + { + Debug(Mso::Memory::AutoIgnoreLeakScope lazy); + return Mso::Memory::AllocateEx(size, Mso::Memory::AllocFlags::ShutdownLeak); + } - static void Deallocate(void* ptr) noexcept - { - Mso::Memory::Free(ptr); - } + static void Deallocate(void* ptr) noexcept + { + Mso::Memory::Free(ptr); + } }; } // namespace Mso diff --git a/libs/object/include/object/objectRefCount.h b/libs/object/include/object/objectRefCount.h index b28bb3a..b124604 100644 --- a/libs/object/include/object/objectRefCount.h +++ b/libs/object/include/object/objectRefCount.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Support for reference counting. + Support for reference counting. */ #pragma once @@ -23,192 +23,201 @@ #pragma push_macro("new") #undef new -#define _MSO_OBJECT_SIMPLEREFCOUNT(TObject) \ - public: \ - bool IsUniqueRef() const noexcept { return m_refCount.load(std::memory_order_acquire) == 1; } \ - Debug(uint32_t RefCount() const noexcept { return m_refCount.load(std::memory_order_acquire); }) \ - \ - template void* operator new(size_t, UseMsoMakeInsteadOfOperatorNew* = nullptr); \ - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TObject) +#define _MSO_OBJECT_SIMPLEREFCOUNT(TObject) \ +public: \ + bool IsUniqueRef() const noexcept \ + { \ + return m_refCount.load(std::memory_order_acquire) == 1; \ + } \ + Debug(uint32_t RefCount() const noexcept { return m_refCount.load(std::memory_order_acquire); }) \ + \ + template \ + void* operator new(size_t, UseMsoMakeInsteadOfOperatorNew* = nullptr); \ + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TObject) #define _MSO_OBJECT_NOREFCOUNT(TObject) \ - public: \ - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TObject) +public: \ + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TObject) namespace Mso { template struct SimpleRefCountMemoryGuard { - ~SimpleRefCountMemoryGuard() noexcept - { - if (ObjMemory) - { - TAllocator::Deallocate(ObjMemory); - } - else if (Obj) - { - Obj->Release(); - } - } + ~SimpleRefCountMemoryGuard() noexcept + { + if (ObjMemory) + { + TAllocator::Deallocate(ObjMemory); + } + else if (Obj) + { + Obj->Release(); + } + } public: // We use public fields to reduce number of generated methods. - // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates incorrect code for ship builds. - void* ObjMemory; - T* Obj; + // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates + // incorrect code for ship builds. + void* ObjMemory; + T* Obj; }; template struct SimpleRefCountPolicy { - using Deleter = TDeleter; - using Allocator = TAllocator; + using Deleter = TDeleter; + using Allocator = TAllocator; - template - using MemoryGuard = SimpleRefCountMemoryGuard; + template + using MemoryGuard = SimpleRefCountMemoryGuard; - template - static void AllocateMemory(_Out_ MemoryGuard& memoryGuard) noexcept - { - memoryGuard.ObjMemory = TAllocator::Allocate(sizeof(T)); - } + template + static void AllocateMemory(_Out_ MemoryGuard& memoryGuard) noexcept + { + memoryGuard.ObjMemory = TAllocator::Allocate(sizeof(T)); + } - template - static void AllocateMemory(_Out_ MemoryGuard& memoryGuard, TAllocArg&& allocArg) noexcept - { - memoryGuard.ObjMemory = TAllocator::Allocate(sizeof(T), std::forward(allocArg)); - } + template + static void AllocateMemory(_Out_ MemoryGuard& memoryGuard, TAllocArg&& allocArg) noexcept + { + memoryGuard.ObjMemory = TAllocator::Allocate(sizeof(T), std::forward(allocArg)); + } - template - static void Delete(T* obj) noexcept - { - obj->~T(); - TAllocator::Deallocate(obj); - } + template + static void Delete(T* obj) noexcept + { + obj->~T(); + TAllocator::Deallocate(obj); + } #if DEBUG - template - static void ValidateObject(MemoryGuard& memoryGuard) noexcept - { - static_assert(offsetof(typename T::TypeToDelete, m_refCount) == offsetof(T, m_refCount), - "Ref counted object must be the first type in T inheritance list."); + template + static void ValidateObject(MemoryGuard& memoryGuard) noexcept + { + static_assert( + offsetof(typename T::TypeToDelete, m_refCount) == offsetof(T, m_refCount), + "Ref counted object must be the first type in T inheritance list."); - VerifyElseCrashSzTag(memoryGuard.Obj, "Object was not created", 0x01105590 /* tag_befwq */); - VerifyElseCrashSzTag(reinterpret_cast(memoryGuard.Obj) == static_cast(memoryGuard.Obj), - "Ref counted object must be the first type in T inheritance list.", 0x01105591 /* tag_befwr */); - } + VerifyElseCrashSzTag(memoryGuard.Obj, "Object was not created", 0x01105590 /* tag_befwq */); + VerifyElseCrashSzTag( + reinterpret_cast(memoryGuard.Obj) == static_cast(memoryGuard.Obj), + "Ref counted object must be the first type in T inheritance list.", + 0x01105591 /* tag_befwr */); + } #endif }; struct DefaultRefCountedDeleter { - template - static void Delete(TObject* obj) noexcept - { - TObject::RefCountPolicy::template Delete(obj); - } + template + static void Delete(TObject* obj) noexcept + { + TObject::RefCountPolicy::template Delete(obj); + } }; /** - Supported Object ref count strategies. They are used to select base class for ref counting and to choose Make algorithm. - The struct can be changed to a namespace if in future we need many strategies in different files. + Supported Object ref count strategies. They are used to select base class for ref counting and to choose Make + algorithm. The struct can be changed to a namespace if in future we need many strategies in different files. */ namespace RefCountStrategy { - using Simple = SimpleRefCountPolicy; - struct SimpleNoQuery; - struct NoRefCount; - struct NoRefCountNoQuery; -}; - - +using Simple = SimpleRefCountPolicy; +struct SimpleNoQuery; +struct NoRefCount; +struct NoRefCountNoQuery; +}; // namespace RefCountStrategy /** - std::shared_ptr is large - it's 2 pointers. - This is handy for cases where memory management (one pointer) is separated from the actual - data (second pointer). But in cases where we have std::shared_ptr and construct it using - std::make_shared() it does not make much sense - we waste one pointer. - An example would be well-defined final types - like std::shared_ptr>. - To avoid wasting memory, created 2 new concepts that mirror STL - RefCountedPtr<> & Make_RefCounted<>() - Helper class RefCountedWrapper is used to facilitate change + std::shared_ptr is large - it's 2 pointers. + This is handy for cases where memory management (one pointer) is separated from the actual + data (second pointer). But in cases where we have std::shared_ptr and construct it using + std::make_shared() it does not make much sense - we waste one pointer. + An example would be well-defined final types - like std::shared_ptr>. + To avoid wasting memory, created 2 new concepts that mirror STL - RefCountedPtr<> & Make_RefCounted<>() + Helper class RefCountedWrapper is used to facilitate change - NOTE: there are potentially 2 types of objects we need: - 1) final & no vtable. Useful for case of std::shared_ptr>. - 2) with virtual destructor. Useful for type eraser, to make sure object is deleted properly. + NOTE: there are potentially 2 types of objects we need: + 1) final & no vtable. Useful for case of std::shared_ptr>. + 2) with virtual destructor. Useful for type eraser, to make sure object is deleted properly. - Also we can do various optimizations / specializations, like - - ref-counted without interlocked operations (where it's safe) - - ref-counting using short (2 bytes), vs. int (useful if to pack better, like case of - RefCountedWrapper> in CallbackStoreCombined - That said, this comes at the cost of complexity - more types, harder to navigate and easier to make mistakes. - Should be done through optional template args. + Also we can do various optimizations / specializations, like + - ref-counted without interlocked operations (where it's safe) + - ref-counting using short (2 bytes), vs. int (useful if to pack better, like case of + RefCountedWrapper> in CallbackStoreCombined + That said, this comes at the cost of complexity - more types, harder to navigate and easier to make mistakes. + Should be done through optional template args. */ class RefCountedWrapperBase { public: - using RefCountPolicy = SimpleRefCountPolicy; - friend RefCountPolicy; + using RefCountPolicy = SimpleRefCountPolicy; + friend RefCountPolicy; - using TypeToDelete = RefCountedWrapperBase; // To verify that TypeToDelete is the first in the inheritance chain. + using TypeToDelete = RefCountedWrapperBase; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedWrapperBase); + _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedWrapperBase); - void AddRef() const noexcept - { - uint32_t refCount = ++m_refCount; - (void)(refCount); - Debug(VerifyElseCrashSzTag(static_cast(refCount) > 1, "Ref count must not bounce from zero", 0x01105592 /* tag_befws */)); - } + void AddRef() const noexcept + { + uint32_t refCount = ++m_refCount; + (void)(refCount); + Debug(VerifyElseCrashSzTag( + static_cast(refCount) > 1, "Ref count must not bounce from zero", 0x01105592 /* tag_befws */)); + } - void Release() const noexcept - { - uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x01105593 /* tag_befwt */)); - if (refCount == 0) - { - RefCountPolicy::Delete(const_cast(this)); - } - } + void Release() const noexcept + { + uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x01105593 /* tag_befwt */)); + if (refCount == 0) + { + RefCountPolicy::Delete(const_cast(this)); + } + } protected: - RefCountedWrapperBase() noexcept = default; - virtual ~RefCountedWrapperBase() noexcept = default; // for type erasure + RefCountedWrapperBase() noexcept = default; + virtual ~RefCountedWrapperBase() noexcept = default; // for type erasure private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; template -class RefCountedWrapper : public RefCountedWrapperBase, public T +class RefCountedWrapper + : public RefCountedWrapperBase + , public T { public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(RefCountedWrapper); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(RefCountedWrapper); - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; - template - RefCountedWrapper(U&&... args) noexcept - : T(std::forward(args)...) - { - } + template + RefCountedWrapper(U&&... args) noexcept : T(std::forward(args)...) + { + } }; /** - Special case for base object that does not know about its type. - Useful for generic containers, where container does not care about the type, - but has external user that can differentiate between instances of these objects - (for example by storing property ID as a first field, i.e. - RefCountedWrapper>) + Special case for base object that does not know about its type. + Useful for generic containers, where container does not care about the type, + but has external user that can differentiate between instances of these objects + (for example by storing property ID as a first field, i.e. + RefCountedWrapper>) */ -template<> +template <> class RefCountedWrapper : public RefCountedWrapperBase { public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(RefCountedWrapper); - RefCountedWrapper() noexcept = default; + DECLARE_COPYCONSTR_AND_ASSIGNMENT(RefCountedWrapper); + RefCountedWrapper() noexcept = default; }; /** - The actual type / Make() function everybody would use + The actual type / Make() function everybody would use */ template using RefCountedPtr = Mso::TCntPtr>; @@ -216,7 +225,7 @@ using RefCountedPtr = Mso::TCntPtr>; template RefCountedPtr Make_RefCounted(U&&... args) noexcept { - return Mso::Make>(std::forward(args)...); + return Mso::Make>(std::forward(args)...); } } // namespace Mso diff --git a/libs/object/include/object/objectWithWeakRef.h b/libs/object/include/object/objectWithWeakRef.h index 9064676..3399d84 100644 --- a/libs/object/include/object/objectWithWeakRef.h +++ b/libs/object/include/object/objectWithWeakRef.h @@ -18,7 +18,7 @@ To implement your classes please use classes defined in the msoUnknownObject.h o // - Expose the reference counting control block as a public API - ObjectWeakRef class. // - Add a base class ObjectWithWeakRef to support TCntPtr. // -// Classes must be inherited from the ObjectWithWeakRef and assigned an instance of ObjectWeakRef right after +// Classes must be inherited from the ObjectWithWeakRef and assigned an instance of ObjectWeakRef right after // the construction. ObjectWithWeakRef delegates all ref counting to ObjectWeakRef. // // ObjectWeakRef is an ObjectRefCount that maintains a m_strongRefCount variable to control the lifetime of classes @@ -34,11 +34,12 @@ To implement your classes please use classes defined in the msoUnknownObject.h o // // To allocate memory we use ObjectWeakRefContainer. It is inherited from the ObjectWeakRef and has storage // for the constructed object. So, we have only one memory allocation instead of two. -// +// // It is very similar to how the std::make_shared works. // The main difference here is that the base class for the ObjectWeakRefContainer is a template which -// gives ability to have different base classes. They just required to have a virtual method DestroyOwnedObject() to signal -// when object must be destroyed. The base class must also have a virtual destructor and be responsible for its destruction. +// gives ability to have different base classes. They just required to have a virtual method DestroyOwnedObject() to +// signal when object must be destroyed. The base class must also have a virtual destructor and be responsible for its +// destruction. // // ------------------------------------------------------------------------------------------- // | ObjectWeakRefContainer | @@ -69,112 +70,121 @@ To implement your classes please use classes defined in the msoUnknownObject.h o #pragma push_macro("new") #undef new -#define _MSO_OBJECT_WEAKREFCOUNT(TObject) \ - public: \ - Mso::ObjectWeakRef& GetWeakRef() const noexcept { return *Mso::Details::GetWeakRef(this); } \ - bool IsUniqueRef() const noexcept { return GetWeakRef().IsUniqueRef(); } \ - Debug(uint32_t RefCount() const noexcept { return GetWeakRef().RefCount(); }) \ - \ - template void* operator new(size_t, UseMsoMakeInsteadOfOperatorNew* = nullptr); \ - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TObject) +#define _MSO_OBJECT_WEAKREFCOUNT(TObject) \ +public: \ + Mso::ObjectWeakRef& GetWeakRef() const noexcept \ + { \ + return *Mso::Details::GetWeakRef(this); \ + } \ + bool IsUniqueRef() const noexcept \ + { \ + return GetWeakRef().IsUniqueRef(); \ + } \ + Debug(uint32_t RefCount() const noexcept { return GetWeakRef().RefCount(); }) \ + \ + template \ + void* operator new(size_t, UseMsoMakeInsteadOfOperatorNew* = nullptr); \ + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TObject) namespace Mso { /** - Reference counting block to support weak pointers. + Reference counting block to support weak pointers. */ MSO_CLASS_GUID(ObjectWeakRef, "3063C26C-DB10-4BCC-AF5C-340E4D7AA0F6") class ObjectWeakRef { public: - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using TypeToDelete = ObjectWeakRef; // To verify that TypeToDelete is the first in the inheritance chain. + using TypeToDelete = ObjectWeakRef; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(ObjectWeakRef); + _MSO_OBJECT_SIMPLEREFCOUNT(ObjectWeakRef); - ObjectWeakRef() = default; + ObjectWeakRef() = default; - void AddRef() const noexcept - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x01105594 /* tag_befwu */)); - } - } + void AddRef() const noexcept + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x01105594 /* tag_befwu */)); + } + } - void Release() const noexcept - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x008c2685 /* tag_a9c0f */)); - if (refCount == 0) - { - const_cast(this)->DestroyObject(); - } - } + void Release() const noexcept + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x008c2685 /* tag_a9c0f */)); + if (refCount == 0) + { + const_cast(this)->DestroyObject(); + } + } - void AddWeakRef() const noexcept - { - if (++m_weakRefCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Weak ref count must not bounce from zero", 0x01105595 /* tag_befwv */)); - } - } + void AddWeakRef() const noexcept + { + if (++m_weakRefCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Weak ref count must not bounce from zero", 0x01105595 /* tag_befwv */)); + } + } - void ReleaseWeakRef() const noexcept - { - const uint32_t weakRefCount = --m_weakRefCount; - Debug(VerifyElseCrashSzTag(static_cast(weakRefCount) >= 0, "Weak ref count must not be negative.", 0x008c2686 /* tag_a9c0g */)); - if (weakRefCount == 0) - { - DestroyContainer(); - } - } + void ReleaseWeakRef() const noexcept + { + const uint32_t weakRefCount = --m_weakRefCount; + Debug(VerifyElseCrashSzTag( + static_cast(weakRefCount) >= 0, "Weak ref count must not be negative.", 0x008c2686 /* tag_a9c0g */)); + if (weakRefCount == 0) + { + DestroyContainer(); + } + } - Debug(uint32_t WeakRefCount() const noexcept { return m_weakRefCount.load(std::memory_order_acquire); }) + Debug(uint32_t WeakRefCount() const noexcept { return m_weakRefCount.load(std::memory_order_acquire); }) - Mso::ObjectWeakRef& GetWeakRef() const noexcept - { - return *const_cast(this); - } + Mso::ObjectWeakRef& GetWeakRef() const noexcept + { + return *const_cast(this); + } - virtual void* QueryCastWeakRef(const GUID& /*riid*/) noexcept - { - return nullptr; - } + virtual void* QueryCastWeakRef(const GUID& /*riid*/) noexcept + { + return nullptr; + } - bool IsExpired() const noexcept - { - return (m_refCount.load(std::memory_order_acquire) == 0); - } + bool IsExpired() const noexcept + { + return (m_refCount.load(std::memory_order_acquire) == 0); + } - bool IncrementRefCountIfNotZero() noexcept - { - uint32_t count = m_refCount.load(std::memory_order_acquire); - for (;;) - { - if (count == 0) - { - return false; - } + bool IncrementRefCountIfNotZero() noexcept + { + uint32_t count = m_refCount.load(std::memory_order_acquire); + for (;;) + { + if (count == 0) + { + return false; + } - if (m_refCount.compare_exchange_weak(/*ref*/count, count + 1)) - { - return true; - } - } - } + if (m_refCount.compare_exchange_weak(/*ref*/ count, count + 1)) + { + return true; + } + } + } - virtual void DestroyObject() noexcept {} + virtual void DestroyObject() noexcept {} protected: - virtual void DestroyContainer() const noexcept = 0; - virtual ~ObjectWeakRef() = default; + virtual void DestroyContainer() const noexcept = 0; + virtual ~ObjectWeakRef() = default; private: - mutable std::atomic m_refCount { 1 }; - mutable std::atomic m_weakRefCount { 1 }; // Controls ObjectWeakRef lifetime. + mutable std::atomic m_refCount{1}; + mutable std::atomic m_weakRefCount{1}; // Controls ObjectWeakRef lifetime. }; namespace Details { @@ -182,195 +192,213 @@ namespace Details { // Weak reference is always stored in object negative space. inline Mso::ObjectWeakRef* GetWeakRef(const void* obj) noexcept { - return *(static_cast(const_cast(obj)) - 1); + return *(static_cast(const_cast(obj)) - 1); } inline void SetWeakRef(const void* obj, Mso::ObjectWeakRef* weakRef) noexcept { - *(static_cast(const_cast(obj)) - 1) = weakRef; + *(static_cast(const_cast(obj)) - 1) = weakRef; } } // namespace Details /** - Allocates RefCountBlock and the target object in the same chunk of memory. - TWeakRef is expected to have a virtual destructor and virtual DestroyOwnedObject method. + Allocates RefCountBlock and the target object in the same chunk of memory. + TWeakRef is expected to have a virtual destructor and virtual DestroyOwnedObject method. */ template -class ObjectWeakRefContainer - : public TWeakRef +class ObjectWeakRefContainer : public TWeakRef { public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(ObjectWeakRefContainer); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(ObjectWeakRefContainer); - ObjectWeakRefContainer() = default; + ObjectWeakRefContainer() = default; - TObject* Get() noexcept - { - return reinterpret_cast(&m_objectStorage); - } + TObject* Get() noexcept + { + return reinterpret_cast(&m_objectStorage); + } protected: - virtual void DestroyObject() noexcept override - { - TWeakRef::DestroyObject(); + virtual void DestroyObject() noexcept override + { + TWeakRef::DestroyObject(); - TObject* obj = Get(); - if (Mso::Details::GetWeakRef(obj)) // Check if object was correctly initialized. - { - // Call the TObject destructor last: this call may destroy the ObjectWeakRefContainer because it may hold the last reference. - TObject::RefCountPolicy::Deleter::Delete(static_cast(obj)); - } - } + TObject* obj = Get(); + if (Mso::Details::GetWeakRef(obj)) // Check if object was correctly initialized. + { + // Call the TObject destructor last: this call may destroy the ObjectWeakRefContainer because it may hold the last + // reference. + TObject::RefCountPolicy::Deleter::Delete(static_cast(obj)); + } + } - virtual void DestroyContainer() const noexcept override - { - this->~ObjectWeakRefContainer(); - TObject::RefCountPolicy::Allocator::Deallocate(const_cast(this)); - } + virtual void DestroyContainer() const noexcept override + { + this->~ObjectWeakRefContainer(); + TObject::RefCountPolicy::Allocator::Deallocate(const_cast(this)); + } private: - ObjectWeakRef* m_weakRefPlaceholder; // reserves negative space before m_objectStorage - typename std::aligned_storage::value>::type m_objectStorage; + ObjectWeakRef* m_weakRefPlaceholder; // reserves negative space before m_objectStorage + typename std::aligned_storage::value>::type m_objectStorage; }; template struct WeakRefCountMemoryGuard { - using Type = T; + using Type = T; - ~WeakRefCountMemoryGuard() noexcept - { - if (ObjMemory) - { - // Constructor failed, Make sure that destructor is not called. - ObjectWeakRef* weakRef = Mso::Details::GetWeakRef(ObjMemory); - Mso::Details::SetWeakRef(ObjMemory, nullptr); // This should prevent destructor call. - Container->Release(); // Release the strong reference which we add to object when we create it. - weakRef->ReleaseWeakRef(); // WeakRef is released when object is destroyed. This call may destroy container and must be the last. - } - else if (Obj) - { - // Initialization failed. Use normal object destruction sequence. - Obj->Release(); - } - } + ~WeakRefCountMemoryGuard() noexcept + { + if (ObjMemory) + { + // Constructor failed, Make sure that destructor is not called. + ObjectWeakRef* weakRef = Mso::Details::GetWeakRef(ObjMemory); + Mso::Details::SetWeakRef(ObjMemory, nullptr); // This should prevent destructor call. + Container->Release(); // Release the strong reference which we add to object when we create it. + weakRef->ReleaseWeakRef(); // WeakRef is released when object is destroyed. This call may destroy container and + // must be the last. + } + else if (Obj) + { + // Initialization failed. Use normal object destruction sequence. + Obj->Release(); + } + } public: // We use a public fields to reduce number of generated methods. - // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates incorrect code for ship builds. - void* ObjMemory; - T* Obj; - TContainer* Container; + // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates + // incorrect code for ship builds. + void* ObjMemory; + T* Obj; + TContainer* Container; }; template struct WeakRefCountPolicy { - using Deleter = TDeleter; - using Allocator = TAllocator; + using Deleter = TDeleter; + using Allocator = TAllocator; - template > - using MemoryGuard = WeakRefCountMemoryGuard; + template > + using MemoryGuard = WeakRefCountMemoryGuard; - template - static void AllocateMemory(_Out_ MemoryGuard& memoryGuard) noexcept - { - void* containerMemory = TAllocator::Allocate(sizeof(TContainer)); - if (containerMemory) - { - memoryGuard.Container = ::new (containerMemory) TContainer(); - memoryGuard.ObjMemory = memoryGuard.Container->Get(); - Mso::Details::SetWeakRef(memoryGuard.ObjMemory, memoryGuard.Container); - } - } + template + static void AllocateMemory(_Out_ MemoryGuard& memoryGuard) noexcept + { + void* containerMemory = TAllocator::Allocate(sizeof(TContainer)); + if (containerMemory) + { + memoryGuard.Container = ::new (containerMemory) TContainer(); + memoryGuard.ObjMemory = memoryGuard.Container->Get(); + Mso::Details::SetWeakRef(memoryGuard.ObjMemory, memoryGuard.Container); + } + } - template - static void AllocateMemory(_Out_ MemoryGuard& memoryGuard, TAllocArg&& allocArg) noexcept - { - void* containerMemory = TAllocator::Allocate(sizeof(TContainer), std::forward(allocArg)); - if (containerMemory) - { - memoryGuard.Container = ::new (containerMemory) TContainer(); - memoryGuard.ObjMemory = memoryGuard.Container->Get(); - Mso::Details::SetWeakRef(memoryGuard.ObjMemory, memoryGuard.Container); - } - } + template + static void AllocateMemory(_Out_ MemoryGuard& memoryGuard, TAllocArg&& allocArg) noexcept + { + void* containerMemory = TAllocator::Allocate(sizeof(TContainer), std::forward(allocArg)); + if (containerMemory) + { + memoryGuard.Container = ::new (containerMemory) TContainer(); + memoryGuard.ObjMemory = memoryGuard.Container->Get(); + Mso::Details::SetWeakRef(memoryGuard.ObjMemory, memoryGuard.Container); + } + } - template - static void Delete(T* obj) noexcept - { - obj->~T(); - ObjectWeakRef* weakRef = Mso::Details::GetWeakRef(obj); - Mso::Details::SetWeakRef(obj, nullptr); - weakRef->ReleaseWeakRef(); // This call may destroy container and must be the last. - } + template + static void Delete(T* obj) noexcept + { + obj->~T(); + ObjectWeakRef* weakRef = Mso::Details::GetWeakRef(obj); + Mso::Details::SetWeakRef(obj, nullptr); + weakRef->ReleaseWeakRef(); // This call may destroy container and must be the last. + } #if DEBUG - template - static void ValidateObject(TMemoryGuard& memoryGuard) noexcept - { - VerifyElseCrashSzTag(memoryGuard.Obj, "Object was not created", 0x01105596 /* tag_befww */); - VerifyElseCrashSzTag(reinterpret_cast(memoryGuard.Obj) == static_cast(memoryGuard.Obj), - "Ref counted object must be the first type in T inheritance list.", 0x008c2687 /* tag_a9c0h */); - VerifyElseCrashSzTag(reinterpret_cast(memoryGuard.Container) == &memoryGuard.Obj->GetWeakRef(), "Bad WeakRef", 0x008c2688 /* tag_a9c0i */); - } + template + static void ValidateObject(TMemoryGuard& memoryGuard) noexcept + { + VerifyElseCrashSzTag(memoryGuard.Obj, "Object was not created", 0x01105596 /* tag_befww */); + VerifyElseCrashSzTag( + reinterpret_cast(memoryGuard.Obj) + == static_cast(memoryGuard.Obj), + "Ref counted object must be the first type in T inheritance list.", + 0x008c2687 /* tag_a9c0h */); + VerifyElseCrashSzTag( + reinterpret_cast(memoryGuard.Container) == &memoryGuard.Obj->GetWeakRef(), + "Bad WeakRef", + 0x008c2688 /* tag_a9c0i */); + } #endif }; /** - Extend the supported Object ref count strategies with WeakRef. + Extend the supported Object ref count strategies with WeakRef. */ namespace RefCountStrategy { - using WeakRef = WeakRefCountPolicy; +using WeakRef = WeakRefCountPolicy; } namespace Details { /** - Mso::MakeWeakRefObject creates a new instance of class T in container TContainer and returns a TCntPtr to the instance of type TResult. - TResult is either the original type T (default), or one of its interfaces. - Returning an interface type can help to avoid creation of unnecessary TCntPtr template instances. + Mso::MakeWeakRefObject creates a new instance of class T in container TContainer and returns a TCntPtr to the instance + of type TResult. TResult is either the original type T (default), or one of its interfaces. Returning an interface + type can help to avoid creation of unnecessary TCntPtr template instances. - Method MakeWeakRefObject is noexcept depending on the Make policy noexcept value. + Method MakeWeakRefObject is noexcept depending on the Make policy noexcept value. */ -template , typename... TArgs> +template < + typename T, + typename TResult = T, + typename TContainer = ObjectWeakRefContainer, + typename... TArgs> inline Mso::TCntPtr MakeWeakRefObject(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) { - typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard); - VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774a /* tag_bex3k */); + typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard); + VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774a /* tag_bex3k */); - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return Mso::TCntPtr(result, /*fDoAddRef*/ false); + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return Mso::TCntPtr(result, /*fDoAddRef*/ false); } /** - Mso::MakeAllocWeakRefObject is an Mso::MakeWeakRefObject method for types T that use allocators accepting an argument. - The allocator argument allows to implement stateful allocators. + Mso::MakeAllocWeakRefObject is an Mso::MakeWeakRefObject method for types T that use allocators accepting an argument. + The allocator argument allows to implement stateful allocators. - MakeAllocWeakRefObject creates a new instance of class T in container TContainer and returns a TCntPtr to the instance of type TResult. - TResult is either the original type T (default), or one of its interfaces. - Returning an interface type can help to avoid creation of unnecessary TCntPtr template instantiations. + MakeAllocWeakRefObject creates a new instance of class T in container TContainer and returns a TCntPtr to the instance + of type TResult. TResult is either the original type T (default), or one of its interfaces. Returning an interface + type can help to avoid creation of unnecessary TCntPtr template instantiations. - Method MakeAllocWeakRefObject is noexcept depending on the Make policy noexcept value. + Method MakeAllocWeakRefObject is noexcept depending on the Make policy noexcept value. */ -template , typename TAllocArg, typename... TArgs> -inline Mso::TCntPtr MakeAllocWeakRefObject(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) +template < + typename T, + typename TResult = T, + typename TContainer = ObjectWeakRefContainer, + typename TAllocArg, + typename... TArgs> +inline Mso::TCntPtr MakeAllocWeakRefObject(TAllocArg&& allocArg, TArgs&&... args) noexcept( + T::MakePolicy::IsNoExcept) { - typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); - VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774b /* tag_bex3l */); + typename T::RefCountPolicy::template MemoryGuard memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); + VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774b /* tag_bex3l */); - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return Mso::TCntPtr(result, /*fDoAddRef*/ false); + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return Mso::TCntPtr(result, /*fDoAddRef*/ false); } } // namespace Details diff --git a/libs/object/include/object/queryCast.h b/libs/object/include/object/queryCast.h index 630a862..56109bb 100644 --- a/libs/object/include/object/queryCast.h +++ b/libs/object/include/object/queryCast.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Support for IUnknown::QueryInterface implementation. + Support for IUnknown::QueryInterface implementation. */ #pragma once #include @@ -37,9 +37,12 @@ Here we provide a number of helper templates to implement QueryCast for a type: // Disable warnings 4625 and 4626 because templates below may have or may not have default copy constructor and // copy assignment operator depending on the template type parameter. We do not want just to delete them because // they could be useful in some scenarios when generated. -#pragma warning(disable: 4625) // copy constructor could not be generated because a base class copy constructor is inaccessible or deleted -#pragma warning(disable: 4626) // assignment operator could not be generated because a base class assignment operator is inaccessible or deleted -#pragma warning(disable: 4995) // 'IsDebuggerPresent': name was marked as #pragma deprecated. It is part of VerifyElseCrash macro. +#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy constructor is + // inaccessible or deleted +#pragma warning(disable : 4626) // assignment operator could not be generated because a base class assignment operator + // is inaccessible or deleted +#pragma warning(disable : 4995) // 'IsDebuggerPresent': name was marked as #pragma deprecated. It is part of + // VerifyElseCrash macro. namespace Mso { @@ -47,52 +50,52 @@ namespace Mso { /// Note that we do not call AddRef() here. It is a responsibility of a method that implements IUnknown::QueryInterface. struct QueryCastHelper { - /// Implements QueryCast similar to the classic IUnknown::QueryInterface implementation. - template - static void* QueryCast(_In_ void* obj, const GUID& riid) noexcept - { - // It has lower priority than the next overload because we use void* instead of T* for the obj. - return (riid == __uuidof(T)) ? obj : nullptr; - } + /// Implements QueryCast similar to the classic IUnknown::QueryInterface implementation. + template + static void* QueryCast(_In_ void* obj, const GUID& riid) noexcept + { + // It has lower priority than the next overload because we use void* instead of T* for the obj. + return (riid == __uuidof(T)) ? obj : nullptr; + } - /// Delegates the QueryCast implementation to the object if it has a QueryCast method. - /// If QueryCast fails then we check type's GUID if it is assigned by MSO_STRUCT_GUID or MSO_CLASS_GUID. - template - static auto QueryCast(_In_ T* obj, const GUID& riid) noexcept -> decltype(obj->QueryCast(riid)) - { - void* result = obj->QueryCast(riid); - return (result) ? result : GuidQueryCast(obj, riid, static_cast::Type*>(nullptr)); - } + /// Delegates the QueryCast implementation to the object if it has a QueryCast method. + /// If QueryCast fails then we check type's GUID if it is assigned by MSO_STRUCT_GUID or MSO_CLASS_GUID. + template + static auto QueryCast(_In_ T* obj, const GUID& riid) noexcept -> decltype(obj->QueryCast(riid)) + { + void* result = obj->QueryCast(riid); + return (result) ? result : GuidQueryCast(obj, riid, static_cast::Type*>(nullptr)); + } - /// Recursively calls itself while we have two or more base types. - template - static void* QueryCastList(TSource& obj, const GUID& riid) noexcept - { - void* result = QueryCastList(obj, riid); - return (result) ? result : QueryCastList(obj, riid); - } + /// Recursively calls itself while we have two or more base types. + template + static void* QueryCastList(TSource& obj, const GUID& riid) noexcept + { + void* result = QueryCastList(obj, riid); + return (result) ? result : QueryCastList(obj, riid); + } - /// An implementation for a type list with just one type. - template - static void* QueryCastList(TSource& obj, const GUID& riid) noexcept - { - return QueryCast(static_cast(&obj), riid); - } + /// An implementation for a type list with just one type. + template + static void* QueryCastList(TSource& obj, const GUID& riid) noexcept + { + return QueryCast(static_cast(&obj), riid); + } private: - template - static void* GuidQueryCast(_In_ T* /*obj*/, const GUID& /*riid*/, Mso::Details::GuidUtils::FalseType*) noexcept - { - // Type has no GUID: do nothing - return nullptr; - } + template + static void* GuidQueryCast(_In_ T* /*obj*/, const GUID& /*riid*/, Mso::Details::GuidUtils::FalseType*) noexcept + { + // Type has no GUID: do nothing + return nullptr; + } - template - static void* GuidQueryCast(_In_ T* obj, const GUID& riid, Mso::Details::GuidUtils::TrueType*) noexcept - { - // Typecast to void* to force choosing QueryCast overload that checks type's GUID. - return QueryCast(static_cast(obj), riid); - } + template + static void* GuidQueryCast(_In_ T* obj, const GUID& riid, Mso::Details::GuidUtils::TrueType*) noexcept + { + // Typecast to void* to force choosing QueryCast overload that checks type's GUID. + return QueryCast(static_cast(obj), riid); + } }; /// Helps to implement static cast for the cases when multiple base types implement the same interface. @@ -105,58 +108,61 @@ struct StaticCastHelper; template struct StaticCastHelper { - /// Try to cast the first base type if it is inherited from TTarget. - template - static TTarget* CastFirst(TSource* source) noexcept - { - return CastIf(typename std::is_base_of::type(), source); - } + /// Try to cast the first base type if it is inherited from TTarget. + template + static TTarget* CastFirst(TSource* source) noexcept + { + return CastIf(typename std::is_base_of::type(), source); + } - /// A case when no base types are inherited from TTarget. - template - static TTarget* CastFirst(TSource* /*source*/) noexcept - { - return nullptr; - } + /// A case when no base types are inherited from TTarget. + template + static TTarget* CastFirst(TSource* /*source*/) noexcept + { + return nullptr; + } private: - /// First base type is inherited from TTarget. Cast it to TTarget. - template - static TTarget* CastIf(std::true_type /*isConvertible?*/, TSource* source) noexcept - { - return Cast(/*tag:*/ 0, static_cast(source)); - } + /// First base type is inherited from TTarget. Cast it to TTarget. + template + static TTarget* CastIf(std::true_type /*isConvertible?*/, TSource* source) noexcept + { + return Cast(/*tag:*/ 0, static_cast(source)); + } - /// First base type is not inherited from TTarget. Recursively call CastFirst for the remaining base types. - template - static TTarget* CastIf(std::false_type /*isConvertible?*/, TSource* source) noexcept - { - return CastFirst(source); - } + /// First base type is not inherited from TTarget. Recursively call CastFirst for the remaining base types. + template + static TTarget* CastIf(std::false_type /*isConvertible?*/, TSource* source) noexcept + { + return CastFirst(source); + } - /// To have a lower priority when matching an int tag parameter. - struct IntWrapper { IntWrapper(int) noexcept {} }; + /// To have a lower priority when matching an int tag parameter. + struct IntWrapper + { + IntWrapper(int) noexcept {} + }; - /// If TSource has a StaticCastElseNull method then call it to do the static cast. - template - static auto Cast(int /*tag*/, TSource* source) noexcept -> decltype(source->template StaticCastElseNull()) - { - return source->template StaticCastElseNull(); - } + /// If TSource has a StaticCastElseNull method then call it to do the static cast. + template + static auto Cast(int /*tag*/, TSource* source) noexcept -> decltype(source->template StaticCastElseNull()) + { + return source->template StaticCastElseNull(); + } - /// Cast using static_cast. It has a lower priority than previous method because we use IntWrapper tag instead of int. - template - static TTarget* Cast(IntWrapper /*tag*/, TSource* source) noexcept - { - return static_cast(source); - } + /// Cast using static_cast. It has a lower priority than previous method because we use IntWrapper tag instead of int. + template + static TTarget* Cast(IntWrapper /*tag*/, TSource* source) noexcept + { + return static_cast(source); + } }; // // Helper templates to implement QueryCast. // -/// Implements QueryCast for the case when object implements an interface derived from a base interface, and we want to +/// Implements QueryCast for the case when object implements an interface derived from a base interface, and we want to /// to query the base interface by its GUID. /// E.g. struct IDerived : IBase {} /// class MyClass : Mso::QueryCastChain< IDerived, IBase > @@ -164,32 +170,32 @@ template class DECLSPEC_NOVTABLE QueryCastChain : public T { public: - void* QueryCast(const GUID& riid) noexcept - { - return InternalQueryCast(riid); - } + void* QueryCast(const GUID& riid) noexcept + { + return InternalQueryCast(riid); + } protected: - template - QueryCastChain(TArgs&&... args) noexcept : T(std::forward(args)...) - { - } + template + QueryCastChain(TArgs&&... args) noexcept : T(std::forward(args)...) + { + } private: - // Recursively calls itself while we have two or more base types. - template - void* InternalQueryCast(const GUID& riid) noexcept - { - void* result = InternalQueryCast(riid); - return (result) ? result : InternalQueryCast(riid); - } + // Recursively calls itself while we have two or more base types. + template + void* InternalQueryCast(const GUID& riid) noexcept + { + void* result = InternalQueryCast(riid); + return (result) ? result : InternalQueryCast(riid); + } - template - void* InternalQueryCast(const GUID& riid) noexcept - { - static_assert(std::is_base_of::value, "T must be inherited from TBaseType"); - return QueryCastHelper::QueryCast(static_cast(this), riid); - } + template + void* InternalQueryCast(const GUID& riid) noexcept + { + static_assert(std::is_base_of::value, "T must be inherited from TBaseType"); + return QueryCastHelper::QueryCast(static_cast(this), riid); + } }; /// Implements the QueryCast that can return the derived type by its GUID. @@ -198,39 +204,38 @@ template class QueryCastDerived { public: - void* QueryCast(const GUID& riid) noexcept - { - if (riid == __uuidof(T)) - { - return static_cast(this); - } + void* QueryCast(const GUID& riid) noexcept + { + if (riid == __uuidof(T)) + { + return static_cast(this); + } - return nullptr; - } + return nullptr; + } }; /// Allows to associate a GUID for a type that works only in the scope of the QueryCast operation. /// This method can be used if type has no associated GUID, but we still want to query for it. -template (nullptr)> +template (nullptr)> class DECLSPEC_NOVTABLE QueryCastGuid : public T { public: - void* QueryCast(const GUID& riid) noexcept - { - if (*Mso::ResolveGuidPtr::Guid == riid) - { - return static_cast(this); - } + void* QueryCast(const GUID& riid) noexcept + { + if (*Mso::ResolveGuidPtr::Guid == riid) + { + return static_cast(this); + } - return nullptr; - } + return nullptr; + } protected: - template - QueryCastGuid(TArgs&&... args) noexcept : T(std::forward(args)...) - { - } - + template + QueryCastGuid(TArgs&&... args) noexcept : T(std::forward(args)...) + { + } }; /// Implements the QueryCast that does not do any query cast for a type. @@ -240,63 +245,67 @@ template class DECLSPEC_NOVTABLE QueryCastHidden : public T { public: - void* QueryCast(const GUID& /*riid*/) noexcept - { - (void)(this); // To avoid OACR warning that method can be static - return nullptr; - } + void* QueryCast(const GUID& /*riid*/) noexcept + { + (void)(this); // To avoid OACR warning that method can be static + return nullptr; + } protected: - template - QueryCastHidden(TArgs&&... args) noexcept : T(std::forward(args)...) - { - } + template + QueryCastHidden(TArgs&&... args) noexcept : T(std::forward(args)...) + { + } }; /// Delegates the QueryCast implementation to the list of the base types. /// If a constructor with a non-empty set of parameters then they are forwarded to the TBase0. template -class DECLSPEC_NOVTABLE QueryCastList : public TBase0, public TBases... +class DECLSPEC_NOVTABLE QueryCastList + : public TBase0 + , public TBases... { - using CastList = int; //TODO: This is a temporary variable. We will have to expand this concept to implement shallow inheritance tree for UnknownObject. - // The goal is to have "using CastList = CastList" in UnknownObject. - using ThisType = QueryCastList; + using CastList = int; // TODO: This is a temporary variable. We will have to expand this concept to implement shallow + // inheritance tree for UnknownObject. + // The goal is to have "using CastList = CastList" in UnknownObject. + using ThisType = QueryCastList; protected: - template - QueryCastList(TArgs&&... args) noexcept : TBase0(std::forward(args)...) - { - } + template + QueryCastList(TArgs&&... args) noexcept : TBase0(std::forward(args)...) + { + } public: - void* QueryCast(const GUID& riid) noexcept - { - return QueryCastHelper::QueryCastList(*this, riid); - } + void* QueryCast(const GUID& riid) noexcept + { + return QueryCastHelper::QueryCastList(*this, riid); + } - template - TTarget StaticCastElseNull() noexcept - { - return StaticCastHelper::template CastFirst(this); - } + template + TTarget StaticCastElseNull() noexcept + { + return StaticCastHelper::template CastFirst(this); + } -#pragma warning(suppress: 4265) // class has virtual functions, but destructor is not virtual +#pragma warning(suppress : 4265) // class has virtual functions, but destructor is not virtual }; /** - A helper class to call QueryCast method for an object. - There are two supported cases: - (1) type has a QueryCast instance method - (2) type is inherited from IUnknown and the implementation supports initialization of a QueryCastBridge instance - inside its IUnknown::QueryInterface() implementation. - The QueryCast typecasting does not call AddRef. + A helper class to call QueryCast method for an object. + There are two supported cases: + (1) type has a QueryCast instance method + (2) type is inherited from IUnknown and the implementation supports initialization of a QueryCastBridge instance + inside its IUnknown::QueryInterface() implementation. + The QueryCast typecasting does not call AddRef. */ MSO_STRUCT_GUID(QueryCastBridge, "A39D5FC8-0641-4EEE-8C97-DDEF114D487D") struct QueryCastBridge { - // DECLARE_COPYCONSTR_AND_ASSIGNMENT(QueryCastBridge); - void* Object; // It must be a first field. In that case **ppvObject in QueryInterface will have the same semantic as with the normal QueryInterface calls. - const GUID& ObjectId; + // DECLARE_COPYCONSTR_AND_ASSIGNMENT(QueryCastBridge); + void* Object; // It must be a first field. In that case **ppvObject in QueryInterface will have the same semantic as + // with the normal QueryInterface calls. + const GUID& ObjectId; }; namespace Details { @@ -309,69 +318,72 @@ struct QueryCastConverter; // Default case is undefined. template struct QueryCastConverter { - template - static TTarget& QueryCast(const TSource& source) noexcept - { - using SourceType = std::decay_t; - using TargetType = std::decay_t; - static_assert(!std::is_pointer::value, "Cannot convert pointer to a reference."); + template + static TTarget& QueryCast(const TSource& source) noexcept + { + using SourceType = std::decay_t; + using TargetType = std::decay_t; + static_assert(!std::is_pointer::value, "Cannot convert pointer to a reference."); - SourceType* nonConstSource = const_cast(&source); - QueryCastBridge bridge = { nullptr, __uuidof(TargetType) }; - VerifySucceededElseCrashTag(nonConstSource->QueryInterface(__uuidof(QueryCastBridge), reinterpret_cast(&bridge)), 0x0100370d /* tag_bad2n */); + SourceType* nonConstSource = const_cast(&source); + QueryCastBridge bridge = {nullptr, __uuidof(TargetType)}; + VerifySucceededElseCrashTag( + nonConstSource->QueryInterface(__uuidof(QueryCastBridge), reinterpret_cast(&bridge)), + 0x0100370d /* tag_bad2n */); - TargetType* target = static_cast(bridge.Object); - VerifyElseCrashSzTag(target, "Query cast failed for a reference type.", 0x0100370e /* tag_bad2o */); - return static_cast(*target); - } + TargetType* target = static_cast(bridge.Object); + VerifyElseCrashSzTag(target, "Query cast failed for a reference type.", 0x0100370e /* tag_bad2o */); + return static_cast(*target); + } }; // Specialization for pointer conversion template struct QueryCastConverter { - template - static TTarget* QueryCast(const TSource& source) noexcept - { - using SourceType = std::remove_const_t>>; - using TargetType = std::decay_t; - static_assert(std::is_pointer::value, "Cannot convert non-pointer to a pointer."); + template + static TTarget* QueryCast(const TSource& source) noexcept + { + using SourceType = std::remove_const_t>>; + using TargetType = std::decay_t; + static_assert(std::is_pointer::value, "Cannot convert non-pointer to a pointer."); - if (source != nullptr) - { - SourceType* nonConstSource = const_cast(source); - QueryCastBridge bridge = { nullptr, __uuidof(TargetType) }; - if (nonConstSource->QueryInterface(__uuidof(QueryCastBridge), reinterpret_cast(&bridge)) == S_OK) - { - TargetType* target = static_cast(bridge.Object); - return static_cast(target); - } - } + if (source != nullptr) + { + SourceType* nonConstSource = const_cast(source); + QueryCastBridge bridge = {nullptr, __uuidof(TargetType)}; + if (nonConstSource->QueryInterface(__uuidof(QueryCastBridge), reinterpret_cast(&bridge)) == S_OK) + { + TargetType* target = static_cast(bridge.Object); + return static_cast(target); + } + } - return nullptr; - } + return nullptr; + } }; -}} // namespace Mso::Details +} // namespace Details +} // namespace Mso /** - query_cast does a dynamic cast based on a type GUID. - It does not call AddRef. Caller of this method is responsible for the object's lifetime management. - TTarget is required to be either a pointer or a reference (similar to dynamic_cast). - E.g. query_cast< IMyIntf* >( x ), or query_cast< IMyIntf& >( x ). + query_cast does a dynamic cast based on a type GUID. + It does not call AddRef. Caller of this method is responsible for the object's lifetime management. + TTarget is required to be either a pointer or a reference (similar to dynamic_cast). + E.g. query_cast< IMyIntf* >( x ), or query_cast< IMyIntf& >( x ). - If query_cast fails to convert to a pointer type then it returns nullptr. - If query_cast fails to convert to a reference type then it crashes the app. + If query_cast fails to convert to a pointer type then it returns nullptr. + If query_cast fails to convert to a reference type then it crashes the app. - For this method to work, the TSource class must support initialization of QueryCastBridge struct - when queried for its GUID. UnknownObject in core\msoUnknownObject.h provides all necessary support. + For this method to work, the TSource class must support initialization of QueryCastBridge struct + when queried for its GUID. UnknownObject in core\msoUnknownObject.h provides all necessary support. - query_cast can be used when we want to do a dynamic cast and do not need to call AddRef to control object lifetime. + query_cast can be used when we want to do a dynamic cast and do not need to call AddRef to control object lifetime. */ template TTarget query_cast(TSource&& source) noexcept { - return Mso::Details::QueryCastConverter::QueryCast(std::forward(source)); + return Mso::Details::QueryCastConverter::QueryCast(std::forward(source)); } #pragma warning(pop) diff --git a/libs/object/include/object/refCounted.h b/libs/object/include/object/refCounted.h index 6534cac..cafcd04 100644 --- a/libs/object/include/object/refCounted.h +++ b/libs/object/include/object/refCounted.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Helper classes for internal ref-counting + Helper classes for internal ref-counting */ #pragma once #include diff --git a/libs/object/include/object/refCountedObject.h b/libs/object/include/object/refCountedObject.h index a39ead0..0c13e2e 100644 --- a/libs/object/include/object/refCountedObject.h +++ b/libs/object/include/object/refCountedObject.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - IRefCounted implementation. + IRefCounted implementation. */ #pragma once @@ -21,528 +21,538 @@ BEGIN_DISABLE_WARNING_INCONSISTENT_MISSING_OVERRIDE() namespace Mso { /** - RefCountedObject is a class template to implement the IRefCounted interface. + RefCountedObject is a class template to implement the IRefCounted interface. - Because RefCountedObject overrides AddRef and Release, at least one of your base types should - declare virtual AddRef/Release methods. Usually you'd specify at least "Mso::IRefCounted" or - some interface that derives from IRefCounted. + Because RefCountedObject overrides AddRef and Release, at least one of your base types should + declare virtual AddRef/Release methods. Usually you'd specify at least "Mso::IRefCounted" or + some interface that derives from IRefCounted. - If you want to avoid the overhead of a v-table, you can use RefCountedObjectNoVTable, which - defines non-virtual AddRef/Release methods. These are still compatible with templated - smart pointers like TCntPtr and ComPtr because those smart pointers don't actually use - virtual method dispatch to call AddRef/Release. + If you want to avoid the overhead of a v-table, you can use RefCountedObjectNoVTable, which + defines non-virtual AddRef/Release methods. These are still compatible with templated + smart pointers like TCntPtr and ComPtr because those smart pointers don't actually use + virtual method dispatch to call AddRef/Release. - To implement IUnknown, use Mso::UnknownObject. + To implement IUnknown, use Mso::UnknownObject. - RefCountedObject provides variants that allow for various combinations of weak references, - multiple inheritance, or just implementing IRefCounted. + RefCountedObject provides variants that allow for various combinations of weak references, + multiple inheritance, or just implementing IRefCounted. - Use Mso::Make to instantiate classes that derive from RefCountedObject. + Use Mso::Make to instantiate classes that derive from RefCountedObject. - EXAMPLES - -------- + EXAMPLES + -------- - 1) A simple class that implements IRefCounted: + 1) A simple class that implements IRefCounted: - class Foo : public Mso::RefCountedObject - { - ... - }; + class Foo : public Mso::RefCountedObject + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 2) A class that implements some interface that derives from IRefCounted: + 2) A class that implements some interface that derives from IRefCounted: - struct IBar : public Mso::IRefCounted { ... }; + struct IBar : public Mso::IRefCounted { ... }; - class Foo : public Mso::RefCountedObject - { - ... - }; + class Foo : public Mso::RefCountedObject + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); - Mso::TCntPtr spBar = Mso::Make(); // Create a TCntPtr directly. + Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spBar = Mso::Make(); // Create a TCntPtr directly. - 3) A class that inherits from multiple base types and implements IRefCounted: + 3) A class that inherits from multiple base types and implements IRefCounted: - class Foo : public Mso::RefCountedObject - { - ... - }; + class Foo : public Mso::RefCountedObject + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 4) A class that implements IRefCounted and has support for weak references: + 4) A class that implements IRefCounted and has support for weak references: - class Foo : public Mso::RefCountedObject - { - ... - }; + class Foo : public Mso::RefCountedObject + { + ... + }; - void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) - { - // Use WeakPtr to capture a weak reference. - Mso::WeakPtr wrThis(this); - event.Register([wrThis] - { - // Use GetStrongPtr to resolve the weak reference. - auto spThis = wrThis.GetStrongPtr(); - if (spThis) - spThis->DoSomethingInResponseToEvent(); - }); - } + void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) + { + // Use WeakPtr to capture a weak reference. + Mso::WeakPtr wrThis(this); + event.Register([wrThis] + { + // Use GetStrongPtr to resolve the weak reference. + auto spThis = wrThis.GetStrongPtr(); + if (spThis) + spThis->DoSomethingInResponseToEvent(); + }); + } - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 5) A class that implements IRefCounted with weak references and a custom deleter: + 5) A class that implements IRefCounted with weak references and a custom deleter: - struct FooDeleter - { - template - static void Delete(T* obj) noexcept - { - ... - } - }; + struct FooDeleter + { + template + static void Delete(T* obj) noexcept + { + ... + } + }; - using FooRefCountPolicy = Mso::WeakRefCountPolicy; + using FooRefCountPolicy = Mso::WeakRefCountPolicy; - class Foo : public Mso::RefCountedObject - { - ... - }; + class Foo : public Mso::RefCountedObject + { + ... + }; - void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) - { - // Use WeakPtr to capture a weak reference. - Mso::WeakPtr wrThis(this); - event.Register([wrThis] - { - // Use GetStrongPtr to resolve the weak reference. - auto spThis = wrThis.GetStrongPtr(); - if (spThis) - spThis->DoSomethingInResponseToEvent(); - }); - } + void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) + { + // Use WeakPtr to capture a weak reference. + Mso::WeakPtr wrThis(this); + event.Register([wrThis] + { + // Use GetStrongPtr to resolve the weak reference. + auto spThis = wrThis.GetStrongPtr(); + if (spThis) + spThis->DoSomethingInResponseToEvent(); + }); + } - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 6) A class that implements some IRefCounted-derived interface, with a private constructor. + 6) A class that implements some IRefCounted-derived interface, with a private constructor. - Use 'friend MakePolicy' to make your constructor private. This helps ensure that - people only use Mso::Make to instantiate your class. + Use 'friend MakePolicy' to make your constructor private. This helps ensure that + people only use Mso::Make to instantiate your class. - struct IBar : public Mso::IRefCounted { ... }; + struct IBar : public Mso::IRefCounted { ... }; - class Foo : public Mso::RefCountedObject - { - friend MakePolicy; + class Foo : public Mso::RefCountedObject + { + friend MakePolicy; - private: - Foo(const Bar& bar) noexcept { ... } // Private constructor + private: + Foo(const Bar& bar) noexcept { ... } // Private constructor - ... - }; + ... + }; - const Bar& bar = ...; - Mso::TCntPtr spFoo = Mso::Make(bar); + const Bar& bar = ...; + Mso::TCntPtr spFoo = Mso::Make(bar); - 7) A class that uses the 'InitializeThis' pattern, which allows you to separate object construction - from other initialization. + 7) A class that uses the 'InitializeThis' pattern, which allows you to separate object construction + from other initialization. - If InitializeThis returns false, Mso::Make will crash the app. + If InitializeThis returns false, Mso::Make will crash the app. - struct IBar : public Mso::IRefCounted { ... }; + struct IBar : public Mso::IRefCounted { ... }; - class Foo : public Mso::RefCountedObject - { - public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + class Foo : public Mso::RefCountedObject + { + public: + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - Foo() noexcept { ... } + Foo() noexcept { ... } - bool InitializeThis(const Baz& baz, const Qux& qux) - { - ... + bool InitializeThis(const Baz& baz, const Qux& qux) + { + ... - // Return 'true' to indicate the object was successfully initialized. 'false' will crash the app. - return true; - } - }; + // Return 'true' to indicate the object was successfully initialized. 'false' will crash the app. + return true; + } + }; - const Baz& baz = ...; - const Qux& qux = ...; - Mso::TCntPtr spFoo = Mso::Make(baz, qux); + const Baz& baz = ...; + const Qux& qux = ...; + Mso::TCntPtr spFoo = Mso::Make(baz, qux); - 8) A class that uses ref counting without a v-table. + 8) A class that uses ref counting without a v-table. - Non-virtual AddRef and Release methods are implemented. These are still compatible with most - template-based smart-pointers (like TCntPtr and ComPtr) since they call 'AddRef' and 'Release' - by name and not necessarily through virtual-method dispatch. + Non-virtual AddRef and Release methods are implemented. These are still compatible with most + template-based smart-pointers (like TCntPtr and ComPtr) since they call 'AddRef' and 'Release' + by name and not necessarily through virtual-method dispatch. - Note that RefCountedObjectNoVTable uses the "Curiously Recursive Template Pattern" which requires - that the derived type be passed in as a template parameter. + Note that RefCountedObjectNoVTable uses the "Curiously Recursive Template Pattern" which requires + that the derived type be passed in as a template parameter. - class Foo : public Mso::RefCountedObjectNoVTable - { - ... - }; + class Foo : public Mso::RefCountedObjectNoVTable + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 9) A class that implements IRefCounted without actual ref counting. + 9) A class that implements IRefCounted without actual ref counting. - This can be useful if the object's lifetime is managed via some other method, but the object - still needs to be used with TCntPtr or other code that expects AddRef/Release. - This often happens in two scenarios: + This can be useful if the object's lifetime is managed via some other method, but the object + still needs to be used with TCntPtr or other code that expects AddRef/Release. + This often happens in two scenarios: - - Singletons that want to avoid any AddRef/Release because there is one long-lived instance. - - Stack-based allocations for unit tests. + - Singletons that want to avoid any AddRef/Release because there is one long-lived instance. + - Stack-based allocations for unit tests. - class Foo : public Mso::RefCountedObject - { - ... - }; + class Foo : public Mso::RefCountedObject + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 10) A class that implements IRefCounted with a custom stateless allocator. + 10) A class that implements IRefCounted with a custom stateless allocator. - struct FooAllocator - { - static void* Allocate(size_t size) noexcept - { - ... - } + struct FooAllocator + { + static void* Allocate(size_t size) noexcept + { + ... + } - static void Deallocate(void* ptr) noexcept - { - ... - } - }; + static void Deallocate(void* ptr) noexcept + { + ... + } + }; - struct IBar : public Mso::IRefCounted { ... }; + struct IBar : public Mso::IRefCounted { ... }; - class Foo : public Mso::RefCountedObject, IBar> - { - ... - }; + class Foo : public Mso::RefCountedObject, + IBar> + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 11) A class that implements IRefCounted with a custom stateful allocator. + 11) A class that implements IRefCounted with a custom stateful allocator. - struct ICustomHeap - { - virtual void* Alloc(size_t size) noexcept = 0; - virtual void Free(void* ptr) noexcept = 0; - }; + struct ICustomHeap + { + virtual void* Alloc(size_t size) noexcept = 0; + virtual void Free(void* ptr) noexcept = 0; + }; - struct FooAllocator - { - static void* Allocate(size_t size, ICustomHeap* heap) noexcept - { - ... - } + struct FooAllocator + { + static void* Allocate(size_t size, ICustomHeap* heap) noexcept + { + ... + } - static void Deallocate(void* ptr) noexcept - { - ... - } - }; + static void Deallocate(void* ptr) noexcept + { + ... + } + }; - struct IBar : public Mso::IRefCounted { ... }; + struct IBar : public Mso::IRefCounted { ... }; - class Foo : public Mso::RefCountedObject, IBar> - { - ... - }; + class Foo : public Mso::RefCountedObject, + IBar> + { + ... + }; - ICustomHeap& heap = ...; - Mso::TCntPtr spFoo = Mso::Make(&heap); + ICustomHeap& heap = ...; + Mso::TCntPtr spFoo = Mso::Make(&heap); - 12) A class that has a throwing ctor and implements IRefCounted: + 12) A class that has a throwing ctor and implements IRefCounted: - struct Foo : public Mso::RefCountedObject - { - using MakePolicy = Mso::MakePolicy::ThrowCtor; + struct Foo : public Mso::RefCountedObject + { + using MakePolicy = Mso::MakePolicy::ThrowCtor; - Foo(); // can throw - ... - }; + Foo(); // can throw + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); // can throw + Mso::TCntPtr spFoo = Mso::Make(); // can throw */ template class RefCountedObject - : public TBaseType0 - , public TBaseTypes... + : public TBaseType0 + , public TBaseTypes... { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" - using TypeToDelete = RefCountedObject; // To verify that TypeToDelete is the first in the inheritance chain. + using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" + using TypeToDelete = RefCountedObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObject); + _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObject); - void AddRef() const noexcept override - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x01105597 /* tag_befwx */)); - } - } + void AddRef() const noexcept override + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x01105597 /* tag_befwx */)); + } + } - void Release() const noexcept override - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x01105598 /* tag_befwy */)); - if (refCount == 0) - { - RefCountPolicy::Delete(const_cast(this)); - } - } + void Release() const noexcept override + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x01105598 /* tag_befwy */)); + if (refCount == 0) + { + RefCountPolicy::Delete(const_cast(this)); + } + } protected: - template - RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) {} + template + RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) + { + } - virtual ~RefCountedObject() = default; + virtual ~RefCountedObject() = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - template class RefCountedObject, TBaseType0, TBaseTypes...> - : public TBaseType0 - , public TBaseTypes... + : public TBaseType0 + , public TBaseTypes... { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" - using TypeToDelete = RefCountedObject; // To verify that TypeToDelete is the first in the inheritance chain. + using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" + using TypeToDelete = RefCountedObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObject); + _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObject); - void AddRef() const noexcept override - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x01105599 /* tag_befwz */)); - } - } + void AddRef() const noexcept override + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x01105599 /* tag_befwz */)); + } + } - void Release() const noexcept override - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x0110559a /* tag_befw0 */)); - if (refCount == 0) - { - TDeleter::Delete(const_cast(this)); - } - } + void Release() const noexcept override + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x0110559a /* tag_befw0 */)); + if (refCount == 0) + { + TDeleter::Delete(const_cast(this)); + } + } protected: - template - RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) {} + template + RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) + { + } - virtual ~RefCountedObject() = default; + virtual ~RefCountedObject() = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - template class RefCountedObject, TBaseType0, TBaseTypes...> - : public TBaseType0 - , public TBaseTypes... + : public TBaseType0 + , public TBaseTypes... { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::WeakRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::WeakRefCountPolicy; + friend RefCountPolicy; - using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" - using TypeToDelete = RefCountedObject; // To verify that TypeToDelete is the first in the inheritance chain. + using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" + using TypeToDelete = RefCountedObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_WEAKREFCOUNT(RefCountedObject); + _MSO_OBJECT_WEAKREFCOUNT(RefCountedObject); - void AddRef() const noexcept override - { - GetWeakRef().AddRef(); - } + void AddRef() const noexcept override + { + GetWeakRef().AddRef(); + } - void Release() const noexcept override - { - GetWeakRef().Release(); - } + void Release() const noexcept override + { + GetWeakRef().Release(); + } protected: - template - RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) {} + template + RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) + { + } - virtual ~RefCountedObject() = default; + virtual ~RefCountedObject() = default; }; - template class RefCountedObject - : public TBaseType0 - , public TBaseTypes... + : public TBaseType0 + , public TBaseTypes... { public: - using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" + using RefCountedObjectType = RefCountedObject; // To use in derived class as "using Super = RefCountedObjectType" - _MSO_OBJECT_NOREFCOUNT(RefCountedObject); + _MSO_OBJECT_NOREFCOUNT(RefCountedObject); - template - RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) {} + template + RefCountedObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) + { + } - void AddRef() const noexcept override {} - void Release() const noexcept override {} - virtual ~RefCountedObject() = default; + void AddRef() const noexcept override {} + void Release() const noexcept override {} + virtual ~RefCountedObject() = default; }; - template class RefCountedObjectNoVTable; - /** - A base class for ref counted objects that do not have v-table and need a simple ref count. + A base class for ref counted objects that do not have v-table and need a simple ref count. */ template class RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using RefCountedObjectNoVTableType = RefCountedObjectNoVTable; // To use in derived class as "using Super = RefCountedObjectNoVTableType" - using TypeToDelete = TDerived; // To verify that TypeToDelete is the first in the inheritance chain. + using RefCountedObjectNoVTableType = + RefCountedObjectNoVTable; // To use in derived class as "using Super = RefCountedObjectNoVTableType" + using TypeToDelete = TDerived; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObjectNoVTable); + _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObjectNoVTable); - void AddRef() const noexcept - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x0110559b /* tag_befw1 */)); - } - } + void AddRef() const noexcept + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x0110559b /* tag_befw1 */)); + } + } - void Release() const noexcept - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x0110559c /* tag_befw2 */)); - if (refCount == 0) - { - RefCountPolicy::Delete(const_cast(static_cast(this))); - } - } + void Release() const noexcept + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x0110559c /* tag_befw2 */)); + if (refCount == 0) + { + RefCountPolicy::Delete(const_cast(static_cast(this))); + } + } protected: - RefCountedObjectNoVTable() = default; + RefCountedObjectNoVTable() = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - /** - A base class for RefCounted objects that do not have v-table and need a simple ref count. + A base class for RefCounted objects that do not have v-table and need a simple ref count. */ template class RefCountedObjectNoVTable, TDerived> { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using RefCountedObjectNoVTableType = RefCountedObjectNoVTable; // To use in derived class as "using Super = RefCountedObjectNoVTableType" - using TypeToDelete = TDerived; // To verify that TypeToDelete is the first in the inheritance chain. + using RefCountedObjectNoVTableType = + RefCountedObjectNoVTable; // To use in derived class as "using Super = RefCountedObjectNoVTableType" + using TypeToDelete = TDerived; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObjectNoVTable); + _MSO_OBJECT_SIMPLEREFCOUNT(RefCountedObjectNoVTable); - void AddRef() const noexcept - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x0110559d /* tag_befw3 */)); - } - } + void AddRef() const noexcept + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x0110559d /* tag_befw3 */)); + } + } - void Release() const noexcept - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x0110559e /* tag_befw4 */)); - if (refCount == 0) - { - TDeleter::Delete(const_cast(static_cast(this))); - } - } + void Release() const noexcept + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x0110559e /* tag_befw4 */)); + if (refCount == 0) + { + TDeleter::Delete(const_cast(static_cast(this))); + } + } protected: - RefCountedObjectNoVTable() = default; + RefCountedObjectNoVTable() = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - /** - A base class for RefCounted objects that do not have v-table and need support for weak ref count. + A base class for RefCounted objects that do not have v-table and need support for weak ref count. */ template class RefCountedObjectNoVTable, TDerived> { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::WeakRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::WeakRefCountPolicy; + friend RefCountPolicy; - using RefCountedObjectNoVTableType = RefCountedObjectNoVTable; // To use in derived class as "using Super = RefCountedObjectNoVTableType" - using TypeToDelete = TDerived; // To verify that TypeToDelete is the first in the inheritance chain. + using RefCountedObjectNoVTableType = + RefCountedObjectNoVTable; // To use in derived class as "using Super = RefCountedObjectNoVTableType" + using TypeToDelete = TDerived; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_WEAKREFCOUNT(RefCountedObjectNoVTable); + _MSO_OBJECT_WEAKREFCOUNT(RefCountedObjectNoVTable); - void AddRef() const noexcept - { - GetWeakRef().AddRef(); - } + void AddRef() const noexcept + { + GetWeakRef().AddRef(); + } - void Release() const noexcept - { - GetWeakRef().Release(); - } + void Release() const noexcept + { + GetWeakRef().Release(); + } protected: - RefCountedObjectNoVTable() = default; + RefCountedObjectNoVTable() = default; }; } // namespace Mso diff --git a/libs/object/include/object/swarm.h b/libs/object/include/object/swarm.h index 0db82af..538fbdb 100644 --- a/libs/object/include/object/swarm.h +++ b/libs/object/include/object/swarm.h @@ -21,7 +21,7 @@ share the same reference counter. // // Any class that is inherited from UnknownObjectWithWeakRef can be part of a swarm. // -// Use SwarmMemberPtr or WeakPtr to reference swarm members between each other. Using TCntPtr between +// Use SwarmMemberPtr or WeakPtr to reference swarm members between each other. Using TCntPtr between // swarm members may cause a memory leak because of an extra ref count to itself. // SwarmMemberPtr may be used for strong pointers and WeakPtr for weak pointers. // Do not use the ObjectWeakRef for weak pointers because there is only one ObjectWeakRef for all swarm members. @@ -35,8 +35,10 @@ share the same reference counter. #pragma pack(push, _CRT_PACKING) #pragma warning(push) -#pragma warning(disable: 4625) // copy constructor could not be generated because a base class copy constructor is inaccessible or deleted -#pragma warning(disable: 4626) // assignment operator could not be generated because a base class assignment operator is inaccessible or deleted +#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy constructor is + // inaccessible or deleted +#pragma warning(disable : 4626) // assignment operator could not be generated because a base class assignment operator + // is inaccessible or deleted #pragma push_macro("new") #undef new @@ -48,44 +50,43 @@ namespace Details { template struct ObjectWeakRefContainerDeleter { - void operator ()(T* ptr) noexcept - { - if (ptr) - { - ptr->DestroyContainer(); - } - } + void operator()(T* ptr) noexcept + { + if (ptr) + { + ptr->DestroyContainer(); + } + } }; } // namespace Details /** - A base class to hold a swarm members. - A swarm member is allocated as a part of the ObjectWeakRefContainer class instance. - SwarmMemberHolder instances form a single linked list. + A base class to hold a swarm members. + A swarm member is allocated as a part of the ObjectWeakRefContainer class instance. + SwarmMemberHolder instances form a single linked list. */ class SwarmMemberHolder { public: - using UniquePtrType = std::unique_ptr>; - static_assert(sizeof(UniquePtrType) == sizeof(void*), "SwarmMemberHolder::UniquePtrType must have a pointer size. It is needed for using InterlockedCompareExchangePointer below."); + using UniquePtrType = std::unique_ptr>; + static_assert( + sizeof(UniquePtrType) == sizeof(void*), + "SwarmMemberHolder::UniquePtrType must have a pointer size. It is needed for using InterlockedCompareExchangePointer below."); - virtual ~SwarmMemberHolder() noexcept - { - } + virtual ~SwarmMemberHolder() noexcept {} protected: - virtual void DestroyObject() noexcept - { - } + virtual void DestroyObject() noexcept {} - virtual void DestroyContainer() const noexcept = 0; + virtual void DestroyContainer() const noexcept = 0; private: - UniquePtrType m_nextMember; // Pointer to the next member in a list. + UniquePtrType m_nextMember; // Pointer to the next member in a list. - friend class Swarm; - template friend struct Details::ObjectWeakRefContainerDeleter; + friend class Swarm; + template + friend struct Details::ObjectWeakRefContainerDeleter; }; // Forward declaration @@ -94,481 +95,474 @@ class Swarm; template struct SwarmMemberMemoryGuard { - using Type = T; + using Type = T; - ~SwarmMemberMemoryGuard() noexcept; + ~SwarmMemberMemoryGuard() noexcept; public: // We use a public fields to reduce number of generated methods. - // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates incorrect code for ship builds. - void* ObjMemory; - T* Obj; - Swarm* Container; - TContainer* MemberContainer; + // VC++ bug: Make sure that the order of the fields is the same for all memory guards. Otherwise, VC++ generates + // incorrect code for ship builds. + void* ObjMemory; + T* Obj; + Swarm* Container; + TContainer* MemberContainer; }; /** - Swarm is a special ObjectWeakRef that owns 1 or more objects. - When Swarm ref count goes to zero it destroys all objects in the Swarm. - Swarm may have any object inherited from a WeakSourceRefCount. + Swarm is a special ObjectWeakRef that owns 1 or more objects. + When Swarm ref count goes to zero it destroys all objects in the Swarm. + Swarm may have any object inherited from a WeakSourceRefCount. */ MSO_CLASS_GUID(Swarm, "A0252DA6-7817-4536-B265-0A0152781652") -class Swarm - : public ObjectWeakRef +class Swarm : public ObjectWeakRef { - using Super = ObjectWeakRef; - using UniquePtrType = SwarmMemberHolder::UniquePtrType; + using Super = ObjectWeakRef; + using UniquePtrType = SwarmMemberHolder::UniquePtrType; public: - Swarm() noexcept - : ObjectWeakRef() - , m_headMember() - { - } + Swarm() noexcept : ObjectWeakRef(), m_headMember() {} - DECLARE_COPYCONSTR_AND_ASSIGNMENT(Swarm); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(Swarm); - template - static Mso::TCntPtr Make(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) - { - typename T::RefCountPolicy::template MemoryGuard> memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard); - VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774c /* tag_bex3m */); + template + static Mso::TCntPtr Make(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) + { + typename T::RefCountPolicy::template MemoryGuard> memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard); + VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774c /* tag_bex3m */); - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return Mso::TCntPtr(result, /*fDoAddRef*/ false); - } + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return Mso::TCntPtr(result, /*fDoAddRef*/ false); + } - template - static Mso::TCntPtr MakeAlloc(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) - { - typename T::RefCountPolicy::template MemoryGuard> memoryGuard = {}; - T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); - VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774d /* tag_bex3n */); + template + static Mso::TCntPtr MakeAlloc(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) + { + typename T::RefCountPolicy::template MemoryGuard> memoryGuard = {}; + T::RefCountPolicy::AllocateMemory(memoryGuard, std::forward(allocArg)); + VerifyAllocElseCrashTag(memoryGuard.ObjMemory, 0x0111774d /* tag_bex3n */); - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return Mso::TCntPtr(result, /*fDoAddRef*/ false); - } + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return Mso::TCntPtr(result, /*fDoAddRef*/ false); + } - // We return swarm member as a raw pointer because the new object shares ref count with the swarm and in many cases - // we want to avoid the extra AddRef/Release because object's lifetime is already tracked. - template - TResult* MakeMember(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) - { - using Container = ObjectWeakRefContainer; + // We return swarm member as a raw pointer because the new object shares ref count with the swarm and in many cases + // we want to avoid the extra AddRef/Release because object's lifetime is already tracked. + template + TResult* MakeMember(TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) + { + using Container = ObjectWeakRefContainer; - void* containerMemory = T::RefCountPolicy::Allocator::Allocate(sizeof(Container)); - VerifyAllocElseCrashTag(containerMemory, 0x0111774e /* tag_bex3o */); - Container* container = ::new (containerMemory) Container(); - void* objMemory = container->Get(); - SwarmMemberMemoryGuard memoryGuard = { objMemory, nullptr, this, container }; - Mso::Details::SetWeakRef(memoryGuard.ObjMemory, this); - AddWeakRef(); // To match ReleaseWeakRef() call in object destructor. + void* containerMemory = T::RefCountPolicy::Allocator::Allocate(sizeof(Container)); + VerifyAllocElseCrashTag(containerMemory, 0x0111774e /* tag_bex3o */); + Container* container = ::new (containerMemory) Container(); + void* objMemory = container->Get(); + SwarmMemberMemoryGuard memoryGuard = {objMemory, nullptr, this, container}; + Mso::Details::SetWeakRef(memoryGuard.ObjMemory, this); + AddWeakRef(); // To match ReleaseWeakRef() call in object destructor. - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - AddSwarmMember(container); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + AddSwarmMember(container); - memoryGuard.MemberContainer = nullptr; // To prevent memoryGuard from destroying the member container. + memoryGuard.MemberContainer = nullptr; // To prevent memoryGuard from destroying the member container. - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return result; - } + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return result; + } - template - TResult* MakeMemberAlloc(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) - { - using Container = ObjectWeakRefContainer; + template + TResult* MakeMemberAlloc(TAllocArg&& allocArg, TArgs&&... args) noexcept(T::MakePolicy::IsNoExcept) + { + using Container = ObjectWeakRefContainer; - void* containerMemory = T::RefCountPolicy::Allocator::Allocate(sizeof(Container), std::forward(allocArg)); - VerifyAllocElseCrashTag(containerMemory, 0x0111774f /* tag_bex3p */); - Container* container = ::new (containerMemory) Container(); - void* objMemory = container->Get(); - SwarmMemberMemoryGuard memoryGuard = { objMemory, nullptr, this, container }; - Mso::Details::SetWeakRef(memoryGuard.ObjMemory, this); - AddWeakRef(); // To match ReleaseWeakRef() call in object destructor. + void* containerMemory = + T::RefCountPolicy::Allocator::Allocate(sizeof(Container), std::forward(allocArg)); + VerifyAllocElseCrashTag(containerMemory, 0x0111774f /* tag_bex3p */); + Container* container = ::new (containerMemory) Container(); + void* objMemory = container->Get(); + SwarmMemberMemoryGuard memoryGuard = {objMemory, nullptr, this, container}; + Mso::Details::SetWeakRef(memoryGuard.ObjMemory, this); + AddWeakRef(); // To match ReleaseWeakRef() call in object destructor. - T::MakePolicy::template Make(memoryGuard, std::forward(args)...); - Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); - AddSwarmMember(container); + T::MakePolicy::template Make(memoryGuard, std::forward(args)...); + Debug(T::RefCountPolicy::ValidateObject(memoryGuard)); + AddSwarmMember(container); - memoryGuard.MemberContainer = nullptr; // To prevent memoryGuard from destroying the member container. + memoryGuard.MemberContainer = nullptr; // To prevent memoryGuard from destroying the member container. - TResult* result = memoryGuard.Obj; - memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. - return result; - } + TResult* result = memoryGuard.Obj; + memoryGuard.Obj = nullptr; // To prevent memoryGuard from destroying the object. + return result; + } - virtual void* QueryCastWeakRef(const GUID& riid) noexcept override - { - if (riid == __uuidof(Swarm)) - { - return this; - } + virtual void* QueryCastWeakRef(const GUID& riid) noexcept override + { + if (riid == __uuidof(Swarm)) + { + return this; + } - return Super::QueryCastWeakRef(riid); - } + return Super::QueryCastWeakRef(riid); + } - static TCntPtr FromWeakRef(_In_opt_ const ObjectWeakRef* weakRef) noexcept - { - TCntPtr swarm; - if (weakRef) - { - swarm = static_cast(const_cast(weakRef)->QueryCastWeakRef(__uuidof(Swarm))); - } - - return swarm; - } + static TCntPtr FromWeakRef(_In_opt_ const ObjectWeakRef* weakRef) noexcept + { + TCntPtr swarm; + if (weakRef) + { + swarm = static_cast(const_cast(weakRef)->QueryCastWeakRef(__uuidof(Swarm))); + } - template - static TCntPtr FromObject(_In_opt_ T* obj) noexcept - { - return FromObjectInternal(obj, OverloadTag()); - } + return swarm; + } - template - bool Contains(_In_opt_ T* obj) const noexcept - { - TCntPtr swarm = Swarm::FromObjectInternal(obj, OverloadTag()); - return this == swarm.Get(); - } + template + static TCntPtr FromObject(_In_opt_ T* obj) noexcept + { + return FromObjectInternal(obj, OverloadTag()); + } + + template + bool Contains(_In_opt_ T* obj) const noexcept + { + TCntPtr swarm = Swarm::FromObjectInternal(obj, OverloadTag()); + return this == swarm.Get(); + } protected: - using SwarmType = Swarm; + using SwarmType = Swarm; - virtual void DestroyObject() noexcept override - { - for (SwarmMemberHolder* member = m_headMember.get(); member != nullptr; member = member->m_nextMember.get()) - { - member->DestroyObject(); - } + virtual void DestroyObject() noexcept override + { + for (SwarmMemberHolder* member = m_headMember.get(); member != nullptr; member = member->m_nextMember.get()) + { + member->DestroyObject(); + } - Super::DestroyObject(); - } + Super::DestroyObject(); + } private: - template - static auto FromObjectInternal(_In_opt_ T* obj, OverloadTagP1) noexcept -> decltype(obj->GetWeakRef(), TCntPtr()) - { - TCntPtr swarm; - if (obj) - { - swarm = Swarm::FromWeakRef(&obj->GetWeakRef()); - } + template + static auto FromObjectInternal(_In_opt_ T* obj, OverloadTagP1) noexcept + -> decltype(obj->GetWeakRef(), TCntPtr()) + { + TCntPtr swarm; + if (obj) + { + swarm = Swarm::FromWeakRef(&obj->GetWeakRef()); + } - return swarm; - } + return swarm; + } - // This method assumes that obj implements IUnknown. - template - static TCntPtr FromObjectInternal(_In_opt_ T* obj, OverloadTagP2) noexcept - { - TCntPtr swarm; - ObjectWeakRef* weakRef = query_cast(obj); - if (weakRef) - { - swarm = FromWeakRef(weakRef); - } + // This method assumes that obj implements IUnknown. + template + static TCntPtr FromObjectInternal(_In_opt_ T* obj, OverloadTagP2) noexcept + { + TCntPtr swarm; + ObjectWeakRef* weakRef = query_cast(obj); + if (weakRef) + { + swarm = FromWeakRef(weakRef); + } - return swarm; - } + return swarm; + } - void AddSwarmMember(SwarmMemberHolder* holder) noexcept - { - // Atomically set the new member as a head member in the single linked list - for (;;) - { - SwarmMemberHolder* headMember = m_headMember.get(); - UniquePtrType& nextMember = holder->m_nextMember; - nextMember.release(); // To make sure that reset will not delete value when we do second iteration. - nextMember.reset(headMember); - if (std::atomic_compare_exchange_weak((std::atomic*)(void*)&m_headMember, &headMember, holder)) - { - // Success: We were able to put pointer to our new member to the m_headMember without any conflicts. - // The object is now owned by the m_headMember. Make sure that memberContainer does not delete it. - break; - } - } - } + void AddSwarmMember(SwarmMemberHolder* holder) noexcept + { + // Atomically set the new member as a head member in the single linked list + for (;;) + { + SwarmMemberHolder* headMember = m_headMember.get(); + UniquePtrType& nextMember = holder->m_nextMember; + nextMember.release(); // To make sure that reset will not delete value when we do second iteration. + nextMember.reset(headMember); + if (std::atomic_compare_exchange_weak( + (std::atomic*)(void*)&m_headMember, &headMember, holder)) + { + // Success: We were able to put pointer to our new member to the m_headMember without any conflicts. + // The object is now owned by the m_headMember. Make sure that memberContainer does not delete it. + break; + } + } + } private: - UniquePtrType m_headMember; + UniquePtrType m_headMember; }; - // Define SwarmMemberMemoryGuard destructor here to avoid using Swarm class before it is defined. template inline SwarmMemberMemoryGuard::~SwarmMemberMemoryGuard() noexcept { - if (ObjMemory) - { - // Object construction failed. Make sure that we release the weak reference added before construction. - Container->ReleaseWeakRef(); - } - else if (Obj) - { - // Initialize method failed. - T::RefCountPolicy::Deleter::template Delete(static_cast(Obj)); - } + if (ObjMemory) + { + // Object construction failed. Make sure that we release the weak reference added before construction. + Container->ReleaseWeakRef(); + } + else if (Obj) + { + // Initialize method failed. + T::RefCountPolicy::Deleter::template Delete(static_cast(Obj)); + } - if (MemberContainer) - { - MemberContainer->~TContainer(); - T::RefCountPolicy::Allocator::Deallocate(MemberContainer); - } + if (MemberContainer) + { + MemberContainer->~TContainer(); + T::RefCountPolicy::Allocator::Deallocate(MemberContainer); + } } - /** - SwarmMemberPtr can be used by a swarm member to point to another swarm member. - The pointer represents a strong reference. It does not contribute to the reference count if the pointed object - is from the same swarm. This is done to avoid extra add ref count which may cause a memory leak. - SwarmMemberPtr assumes that swarm members implement IUnknown. + SwarmMemberPtr can be used by a swarm member to point to another swarm member. + The pointer represents a strong reference. It does not contribute to the reference count if the pointed object + is from the same swarm. This is done to avoid extra add ref count which may cause a memory leak. + SwarmMemberPtr assumes that swarm members implement IUnknown. */ template class SwarmMemberPtr { public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(SwarmMemberPtr); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(SwarmMemberPtr); - SwarmMemberPtr() noexcept - { - } + SwarmMemberPtr() noexcept {} #if __clang__ -//save the clang warning state and silence warnings about [-Wtautological-undefined-compare]. +// save the clang warning state and silence warnings about [-Wtautological-undefined-compare]. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-undefined-compare" #endif - template ::value>> - SwarmMemberPtr(_In_opt_ TOther* ptr, _In_ const Swarm& ownerSwarm, _In_opt_ const Swarm* otherSwarm = nullptr) noexcept - : m_ptr(ptr) - , m_isDifferentSwarm(&ownerSwarm != (otherSwarm ? otherSwarm : Swarm::FromObject(ptr).Get())) - { - if (m_ptr && m_isDifferentSwarm) - { - m_ptr->AddRef(); - } - } + template ::value>> + SwarmMemberPtr( + _In_opt_ TOther* ptr, + _In_ const Swarm& ownerSwarm, + _In_opt_ const Swarm* otherSwarm = nullptr) noexcept + : m_ptr(ptr), m_isDifferentSwarm(&ownerSwarm != (otherSwarm ? otherSwarm : Swarm::FromObject(ptr).Get())) + { + if (m_ptr && m_isDifferentSwarm) + { + m_ptr->AddRef(); + } + } - template ::value>> - SwarmMemberPtr(_In_opt_ TOther* ptr, _In_ const Mso::ObjectWeakRef& ownerWeak, _In_opt_ const Mso::ObjectWeakRef* otherWeak = nullptr) noexcept - : m_ptr(ptr) - , m_isDifferentSwarm(&ownerWeak != (otherWeak ? otherWeak : Details::WeakPtrBase::GetWeakRef(ptr))) - { - if (m_ptr && m_isDifferentSwarm) - { - m_ptr->AddRef(); - } - } + template ::value>> + SwarmMemberPtr( + _In_opt_ TOther* ptr, + _In_ const Mso::ObjectWeakRef& ownerWeak, + _In_opt_ const Mso::ObjectWeakRef* otherWeak = nullptr) noexcept + : m_ptr(ptr), m_isDifferentSwarm(&ownerWeak != (otherWeak ? otherWeak : Details::WeakPtrBase::GetWeakRef(ptr))) + { + if (m_ptr && m_isDifferentSwarm) + { + m_ptr->AddRef(); + } + } -//resume clang warning state +// resume clang warning state #if __clang__ #pragma clang diagnostic pop #endif - SwarmMemberPtr(SwarmMemberPtr&& from) noexcept - : m_ptr(from.m_ptr) - , m_isDifferentSwarm(from.m_isDifferentSwarm) - { - from.m_ptr = nullptr; - from.m_isDifferentSwarm = false; - } + SwarmMemberPtr(SwarmMemberPtr&& from) noexcept : m_ptr(from.m_ptr), m_isDifferentSwarm(from.m_isDifferentSwarm) + { + from.m_ptr = nullptr; + from.m_isDifferentSwarm = false; + } - ~SwarmMemberPtr() noexcept - { - Reset(); - } + ~SwarmMemberPtr() noexcept + { + Reset(); + } - SwarmMemberPtr& operator=(SwarmMemberPtr&& from) noexcept - { - if (this != &from) - { - SwarmMemberPtr(std::move(from)).Swap(*this); - } + SwarmMemberPtr& operator=(SwarmMemberPtr&& from) noexcept + { + if (this != &from) + { + SwarmMemberPtr(std::move(from)).Swap(*this); + } - return *this; - } + return *this; + } - void Swap(SwarmMemberPtr& other) noexcept - { - using std::swap; - OACR_ASSUME_NOTHROW_BEGIN - swap(m_ptr, other.m_ptr); - swap(m_isDifferentSwarm, other.m_isDifferentSwarm); - OACR_ASSUME_NOTHROW_END - } + void Swap(SwarmMemberPtr& other) noexcept + { + using std::swap; + OACR_ASSUME_NOTHROW_BEGIN + swap(m_ptr, other.m_ptr); + swap(m_isDifferentSwarm, other.m_isDifferentSwarm); + OACR_ASSUME_NOTHROW_END + } - void Reset() noexcept - { - if (m_ptr && m_isDifferentSwarm) - { - m_ptr->Release(); - } + void Reset() noexcept + { + if (m_ptr && m_isDifferentSwarm) + { + m_ptr->Release(); + } - m_ptr = nullptr; - } + m_ptr = nullptr; + } - T* Get() const noexcept - { - return m_ptr; - } + T* Get() const noexcept + { + return m_ptr; + } - T** GetRaw() const noexcept - { - return &m_ptr; - } + T** GetRaw() const noexcept + { + return &m_ptr; + } - bool IsEmpty() const noexcept - { - return m_ptr == nullptr; - } + bool IsEmpty() const noexcept + { + return m_ptr == nullptr; + } - bool IsDifferentSwarm() const noexcept - { - return m_isDifferentSwarm; - } + bool IsDifferentSwarm() const noexcept + { + return m_isDifferentSwarm; + } - T* operator ->() const noexcept - { - AssertTag(!IsEmpty(), 0x01003713 /* tag_bad2t */); - return Get(); - } + T* operator->() const noexcept + { + AssertTag(!IsEmpty(), 0x01003713 /* tag_bad2t */); + return Get(); + } - T& operator *() const noexcept - { - AssertTag(!IsEmpty(), 0x01003714 /* tag_bad2u */); - return *m_ptr; - } + T& operator*() const noexcept + { + AssertTag(!IsEmpty(), 0x01003714 /* tag_bad2u */); + return *m_ptr; + } private: - T* m_ptr = nullptr; - bool m_isDifferentSwarm = false; + T* m_ptr = nullptr; + bool m_isDifferentSwarm = false; }; /** - SwarmMemberPtr specialization for a case when we know for sure that we have a pointer inside of the same Swarm. - In that case we can have just a single pointer field and have less code. - It is preferable to use this smart pointer instead of raw pointer because we preserve semantic of the pointer. - I.e. this is not just a random raw pointer, but a raw pointer which is made according to the specific design decision. + SwarmMemberPtr specialization for a case when we know for sure that we have a pointer inside of the same Swarm. + In that case we can have just a single pointer field and have less code. + It is preferable to use this smart pointer instead of raw pointer because we preserve semantic of the pointer. + I.e. this is not just a random raw pointer, but a raw pointer which is made according to the specific design decision. */ template -class SwarmMemberPtr +class SwarmMemberPtr { public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(SwarmMemberPtr); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(SwarmMemberPtr); - SwarmMemberPtr() noexcept - { - } + SwarmMemberPtr() noexcept {} - template ::value>::type> - SwarmMemberPtr(_In_opt_ TOther* ptr) noexcept - : m_ptr(ptr) - { - } + template ::value>::type> + SwarmMemberPtr(_In_opt_ TOther* ptr) noexcept : m_ptr(ptr) + { + } - SwarmMemberPtr(SwarmMemberPtr&& from) noexcept - : m_ptr(from.m_ptr) - { - from.m_ptr = nullptr; - } + SwarmMemberPtr(SwarmMemberPtr&& from) noexcept : m_ptr(from.m_ptr) + { + from.m_ptr = nullptr; + } - SwarmMemberPtr& operator=(SwarmMemberPtr&& from) noexcept - { - if (this != &from) - { - SwarmMemberPtr(std::move(from)).Swap(*this); - } + SwarmMemberPtr& operator=(SwarmMemberPtr&& from) noexcept + { + if (this != &from) + { + SwarmMemberPtr(std::move(from)).Swap(*this); + } - return *this; - } + return *this; + } - void Swap(SwarmMemberPtr& other) noexcept - { - using std::swap; - OACR_ASSUME_NOTHROW_BEGIN - swap(m_ptr, other.m_ptr); - OACR_ASSUME_NOTHROW_END - } + void Swap(SwarmMemberPtr& other) noexcept + { + using std::swap; + OACR_ASSUME_NOTHROW_BEGIN + swap(m_ptr, other.m_ptr); + OACR_ASSUME_NOTHROW_END + } - void Reset() noexcept - { - m_ptr = nullptr; - } + void Reset() noexcept + { + m_ptr = nullptr; + } - T* Get() const noexcept - { - return m_ptr; - } + T* Get() const noexcept + { + return m_ptr; + } - T** GetRaw() noexcept - { - return &m_ptr; - } + T** GetRaw() noexcept + { + return &m_ptr; + } - bool IsEmpty() const noexcept - { - return m_ptr == nullptr; - } + bool IsEmpty() const noexcept + { + return m_ptr == nullptr; + } - bool IsDifferentSwarm() const noexcept - { - return false; - } + bool IsDifferentSwarm() const noexcept + { + return false; + } - T* operator ->() const noexcept - { - AssertTag(!IsEmpty(), 0x01003715 /* tag_bad2v */); - return m_ptr; - } + T* operator->() const noexcept + { + AssertTag(!IsEmpty(), 0x01003715 /* tag_bad2v */); + return m_ptr; + } - T& operator *() const noexcept - { - AssertTag(!IsEmpty(), 0x01003716 /* tag_bad2w */); - return *m_ptr; - } + T& operator*() const noexcept + { + AssertTag(!IsEmpty(), 0x01003716 /* tag_bad2w */); + return *m_ptr; + } private: - T* m_ptr = nullptr; + T* m_ptr = nullptr; }; template void swap(SwarmMemberPtr& left, SwarmMemberPtr& right) noexcept { - left.Swap(right); + left.Swap(right); } template bool operator==(const SwarmMemberPtr& left, std::nullptr_t) noexcept { - return left.IsEmpty(); + return left.IsEmpty(); } template bool operator==(std::nullptr_t, const SwarmMemberPtr& right) noexcept { - return right.IsEmpty(); + return right.IsEmpty(); } template bool operator!=(const SwarmMemberPtr& left, std::nullptr_t) noexcept { - return !left.IsEmpty(); + return !left.IsEmpty(); } template bool operator!=(std::nullptr_t, const SwarmMemberPtr& right) noexcept { - return !right.IsEmpty(); + return !right.IsEmpty(); } } // namespace Mso diff --git a/libs/object/include/object/unknownObject.h b/libs/object/include/object/unknownObject.h index 2841783..b43da2d 100644 --- a/libs/object/include/object/unknownObject.h +++ b/libs/object/include/object/unknownObject.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - IUnknown implementation. + IUnknown implementation. */ #pragma once @@ -25,689 +25,695 @@ namespace Details { template struct QueryInterfaceHelper { - _Success_(return == S_OK) - static HRESULT QueryInterface(T* obj, const GUID& riid, _Outptr_ void** ppvObject) noexcept - { - VerifyElseCrashSzTag(ppvObject != nullptr, "ppvObject must not be null.", 0x01003717 /* tag_bad2x */); + _Success_(return == S_OK) static HRESULT QueryInterface(T* obj, const GUID& riid, _Outptr_ void** ppvObject) noexcept + { + VerifyElseCrashSzTag(ppvObject != nullptr, "ppvObject must not be null.", 0x01003717 /* tag_bad2x */); #if defined(MSO_ENABLE_QICHECK) && defined(DEBUG) && !defined(__clang__) - // Windows gives un-initialized pointers when querying for IMarshal and IAgileObjectthese interfaces. Ignore them. - if (riid != __uuidof(IMarshal) && riid != __uuidof(IAgileObject)) - { - VerifyElseCrashSzTag(*ppvObject == nullptr, "*ppvObject must be null to avoid memory leaks.", 0x01003718 /* tag_bad2y */); - } + // Windows gives un-initialized pointers when querying for IMarshal and IAgileObjectthese interfaces. Ignore them. + if (riid != __uuidof(IMarshal) && riid != __uuidof(IAgileObject)) + { + VerifyElseCrashSzTag( + *ppvObject == nullptr, "*ppvObject must be null to avoid memory leaks.", 0x01003718 /* tag_bad2y */); + } #endif - // QueryCastBridge is used to QI for an interface without AddRef - const GUID& intfGuid = (riid == __uuidof(QueryCastBridge)) - ? reinterpret_cast(ppvObject)->ObjectId - : riid; + // QueryCastBridge is used to QI for an interface without AddRef + const GUID& intfGuid = + (riid == __uuidof(QueryCastBridge)) ? reinterpret_cast(ppvObject)->ObjectId : riid; - if (intfGuid == __uuidof(IUnknown)) - { - *ppvObject = obj->template StaticCastElseNull(); - } - else - { - *ppvObject = obj->QueryCast(intfGuid); - } + if (intfGuid == __uuidof(IUnknown)) + { + *ppvObject = obj->template StaticCastElseNull(); + } + else + { + *ppvObject = obj->QueryCast(intfGuid); + } - if (!*ppvObject) - { - return E_NOINTERFACE; - } + if (!*ppvObject) + { + return E_NOINTERFACE; + } - if (&riid == &intfGuid) - { - obj->AddRef(); - } + if (&riid == &intfGuid) + { + obj->AddRef(); + } - return S_OK; - } + return S_OK; + } }; } // namespace Details - /** - UnknownObject is a class template that implements the IUnknown interface (AddRef, Release, and QueryInterface). + UnknownObject is a class template that implements the IUnknown interface (AddRef, Release, and QueryInterface). - To implement just Mso::IRefCounted (similar to IUnknown but without QueryInterface), use Mso::RefCountedObject. + To implement just Mso::IRefCounted (similar to IUnknown but without QueryInterface), use Mso::RefCountedObject. - UnknownObject provides variants that allow for various combinations of weak references, - multiple inheritance, or just implementing a simple COM interface that derives from IUnknown. + UnknownObject provides variants that allow for various combinations of weak references, + multiple inheritance, or just implementing a simple COM interface that derives from IUnknown. - Use Mso::Make to instantiate classes that derive from UnknownObject. + Use Mso::Make to instantiate classes that derive from UnknownObject. - EXAMPLES - -------- + EXAMPLES + -------- - 1) A simple class that implements a COM interface that derives from IUnknown. + 1) A simple class that implements a COM interface that derives from IUnknown. - AddRef and Release are implemented using a simple ref-count strategy that does not support weak references. - QueryInterface (QI) is automatically implemented to return the ISomeComInterface pointer when Foo is QI'd for it, - as long as ISomeComeInterface is tagged with one of the MSO guid macros (MSO_STRUCT_GUID/MSO_CLASS_GUID). + AddRef and Release are implemented using a simple ref-count strategy that does not support weak references. + QueryInterface (QI) is automatically implemented to return the ISomeComInterface pointer when Foo is QI'd for it, + as long as ISomeComeInterface is tagged with one of the MSO guid macros (MSO_STRUCT_GUID/MSO_CLASS_GUID). - MSO_STRUCT_GUID(ISomeComInterface, "01234567-ABCD-0123-ABCDEF012345") - struct ISomeComInterface : public IUnknown - { - virtual void DoSomething() = 0; - }; + MSO_STRUCT_GUID(ISomeComInterface, "01234567-ABCD-0123-ABCDEF012345") + struct ISomeComInterface : public IUnknown + { + virtual void DoSomething() = 0; + }; - class Foo : public Mso::UnknownObject - { - public: - void DoSomething() override { ... } - }; + class Foo : public Mso::UnknownObject + { + public: + void DoSomething() override { ... } + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 2) A class that implements multiple COM interfaces. + 2) A class that implements multiple COM interfaces. - QueryInterface is automatically implemented to support each interface that is tagged with one of the MSO guid macros - (MSO_STRUCT_GUID/MSO_CLASS_GUID). + QueryInterface is automatically implemented to support each interface that is tagged with one of the MSO guid macros + (MSO_STRUCT_GUID/MSO_CLASS_GUID). - MSO_STRUCT_GUID(IBar, "01234567-ABCD-0123-ABCDEF012345") - struct IBar : public IUnknown - { - virtual void DoBarStuff() = 0; - }; + MSO_STRUCT_GUID(IBar, "01234567-ABCD-0123-ABCDEF012345") + struct IBar : public IUnknown + { + virtual void DoBarStuff() = 0; + }; - MSO_STRUCT_GUID(IBaz, "76543210-ABCD-0123-012345ABCDEF") - struct IBaz : public IUnknown - { - virtual void DoBazStuff() = 0; - }; + MSO_STRUCT_GUID(IBaz, "76543210-ABCD-0123-012345ABCDEF") + struct IBaz : public IUnknown + { + virtual void DoBazStuff() = 0; + }; - MSO_STRUCT_GUID(IQux, "45670123-ABCD-0123-543210FEDCBA") - struct IQux : public IUnknown - { - virtual void DoQuxStuff() = 0; - }; + MSO_STRUCT_GUID(IQux, "45670123-ABCD-0123-543210FEDCBA") + struct IQux : public IUnknown + { + virtual void DoQuxStuff() = 0; + }; - class Foo : public Mso::UnknownObject - { - public: - void DoBarStuff() override { ... } - void DoBazStuff() override { ... } - void DoQuxStuff() override { ... } - }; + class Foo : public Mso::UnknownObject + { + public: + void DoBarStuff() override { ... } + void DoBazStuff() override { ... } + void DoQuxStuff() override { ... } + }; - Mso::TCntPtr spFoo = Mso::Make(); - Mso::TCntPtr spBar = Mso::Make(); // Create a TCntPtr directly. + Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spBar = Mso::Make(); // Create a TCntPtr directly. - 3) A class that inherits from one or more base classes. + 3) A class that inherits from one or more base classes. - QueryInterface is automatically implemented to support each base type that is tagged with one of the MSO guid macros - (MSO_STRUCT_GUID/MSO_CLASS_GUID). Base classes that derive from QueryCastList can be used to implement other COM - interfaces. + QueryInterface is automatically implemented to support each base type that is tagged with one of the MSO guid macros + (MSO_STRUCT_GUID/MSO_CLASS_GUID). Base classes that derive from QueryCastList can be used to implement other COM + interfaces. - MSO_STRUCT_GUID(IBar, "01234567-ABCD-0123-ABCDEF012345") - struct IBar : public IUnknown - { - virtual void DoBarStuff() noexcept = 0; - }; + MSO_STRUCT_GUID(IBar, "01234567-ABCD-0123-ABCDEF012345") + struct IBar : public IUnknown + { + virtual void DoBarStuff() noexcept = 0; + }; - class BarMixin : public Mso::QueryCastList - { - virtual void DoBarStuff() noexcept override { ... } - }; + class BarMixin : public Mso::QueryCastList + { + virtual void DoBarStuff() noexcept override { ... } + }; - MSO_STRUCT_GUID(SomeBaseType, "76543210-ABCD-0123-012345ABCDEF") - struct SomeBaseType : public IUnknown - { - virtual void DoSomething() = 0; - }; + MSO_STRUCT_GUID(SomeBaseType, "76543210-ABCD-0123-012345ABCDEF") + struct SomeBaseType : public IUnknown + { + virtual void DoSomething() = 0; + }; - class Foo : public Mso::UnknownObject - { - public: - void DoSomething() override { ... } - // Foo::QueryInterface will succeed when queried for IBar, returning a BarMixin* - }; + class Foo : public Mso::UnknownObject + { + public: + void DoSomething() override { ... } + // Foo::QueryInterface will succeed when queried for IBar, returning a BarMixin* + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 4) A class that implements a COM interface and has support for weak references: + 4) A class that implements a COM interface and has support for weak references: - class Foo : public Mso::UnknownObject - { - ... - }; + class Foo : public Mso::UnknownObject + { + ... + }; - void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) - { - // Use WeakPtr to capture a weak reference. - Mso::WeakPtr wrThis(this); - event.Register([wrThis] - { - // Use GetStrongPtr to resolve the weak reference. - auto spThis = wrThis.GetStrongPtr(); - if (spThis) - spThis->DoSomethingInResponseToEvent(); - }); - } + void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) + { + // Use WeakPtr to capture a weak reference. + Mso::WeakPtr wrThis(this); + event.Register([wrThis] + { + // Use GetStrongPtr to resolve the weak reference. + auto spThis = wrThis.GetStrongPtr(); + if (spThis) + spThis->DoSomethingInResponseToEvent(); + }); + } - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 5) A class that implements a COM interface with weak references and a custom deleter: + 5) A class that implements a COM interface with weak references and a custom deleter: - struct FooDeleter - { - template - static void Delete(T* obj) noexcept - { - ... - } - }; + struct FooDeleter + { + template + static void Delete(T* obj) noexcept + { + ... + } + }; - using FooRefCountPolicy = Mso::WeakRefCountPolicy; + using FooRefCountPolicy = Mso::WeakRefCountPolicy; - class Foo : public Mso::UnknownObject - { - ... - }; + class Foo : public Mso::UnknownObject + { + ... + }; - void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) - { - Mso::WeakPtr wrThis(this); - event.Register([wrThis] - { - auto spThis = wrThis.GetStrongPtr(); - if (spThis) - spThis->DoSomethingInResponseToEvent(); - }); - } + void Foo::RegisterForEventRequiringWeakRef(SomeEventSource& event) + { + Mso::WeakPtr wrThis(this); + event.Register([wrThis] + { + auto spThis = wrThis.GetStrongPtr(); + if (spThis) + spThis->DoSomethingInResponseToEvent(); + }); + } - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 6) A class that implements a COM interface, with a private constructor. + 6) A class that implements a COM interface, with a private constructor. - Use 'friend MakePolicy' to make your constructor private. This helps ensure that - people only use Mso::Make to instantiate your class. + Use 'friend MakePolicy' to make your constructor private. This helps ensure that + people only use Mso::Make to instantiate your class. - class Foo : public Mso::UnknownObject - { - friend MakePolicy; + class Foo : public Mso::UnknownObject + { + friend MakePolicy; - private: - Foo(const Bar& bar) { } // Private constructor + private: + Foo(const Bar& bar) { } // Private constructor - ... - }; + ... + }; - const Bar& bar = ...; - Mso::TCntPtr spFoo = Mso::Make(bar); + const Bar& bar = ...; + Mso::TCntPtr spFoo = Mso::Make(bar); - 7) A class that uses the 'InitializeThis' pattern, which allows you to separate object construction - from other initialization. + 7) A class that uses the 'InitializeThis' pattern, which allows you to separate object construction + from other initialization. - If InitializeThis returns false, Mso::Make will crash the app. + If InitializeThis returns false, Mso::Make will crash the app. - Mso::Make does not bubble up exceptions, even from throwing constructors, due to the large code-size - cost of exception handling. + Mso::Make does not bubble up exceptions, even from throwing constructors, due to the large code-size + cost of exception handling. - class Foo : public Mso::UnknownObject - { - public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + class Foo : public Mso::UnknownObject + { + public: + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - Foo() noexcept { ... } + Foo() noexcept { ... } - bool InitializeThis(const Baz& baz, const Qux& qux) - { - ... + bool InitializeThis(const Baz& baz, const Qux& qux) + { + ... - // Return 'true' to indicate the object was successfully initialized. 'false' will crash the app. - return true; - } - }; + // Return 'true' to indicate the object was successfully initialized. 'false' will crash the app. + return true; + } + }; - const Baz& baz = ...; - const Qux& qux = ...; - Mso::TCntPtr spFoo = Mso::Make(baz, qux); + const Baz& baz = ...; + const Qux& qux = ...; + Mso::TCntPtr spFoo = Mso::Make(baz, qux); - 8) A class that implements a COM interface without actual ref counting. + 8) A class that implements a COM interface without actual ref counting. - This can be useful if the object's lifetime is managed via some other method, but the object - still needs to be used with ComPtr, TCntPtr or other code that expects AddRef/Release. - This can happen in several scenarios: + This can be useful if the object's lifetime is managed via some other method, but the object + still needs to be used with ComPtr, TCntPtr or other code that expects AddRef/Release. + This can happen in several scenarios: - - Singletons that want to avoid any AddRef/Release because there is one long-lived instance. - - Stack-based allocations for unit tests. - - Support for an ISimpleUnknown interface that has only a QueryInterface method, and no - AddRef/Release methods. + - Singletons that want to avoid any AddRef/Release because there is one long-lived instance. + - Stack-based allocations for unit tests. + - Support for an ISimpleUnknown interface that has only a QueryInterface method, and no + AddRef/Release methods. - class Foo : public Mso::UnknownObject - { - ... - }; + class Foo : public Mso::UnknownObject + { + ... + }; - 9) A class that implements a COM interface but with an empty (E_FAIL) implementation of - QueryInterface (QI). + 9) A class that implements a COM interface but with an empty (E_FAIL) implementation of + QueryInterface (QI). - This can be useful in targeted cases where you know that QI is not necessary and you don't - want to pay the code-bloat cost of an unused QI implementation, but you also don't want - to switch from IUnknown to Mso::IRefCounted. + This can be useful in targeted cases where you know that QI is not necessary and you don't + want to pay the code-bloat cost of an unused QI implementation, but you also don't want + to switch from IUnknown to Mso::IRefCounted. - class Foo : public Mso::UnknownObject - { - ... - }; + class Foo : public Mso::UnknownObject + { + ... + }; - 10) A class that implements a COM interface but with empty implementations of the IUnknown - methods (AddRef, Release, QueryInterface). + 10) A class that implements a COM interface but with empty implementations of the IUnknown + methods (AddRef, Release, QueryInterface). - class Foo : public Mso::UnknownObject - { - ... - }; + class Foo : public Mso::UnknownObject + { + ... + }; - 11) A class that implements IRefCounted with a custom stateless allocator. + 11) A class that implements IRefCounted with a custom stateless allocator. - struct FooAllocator - { - static void* Allocate(size_t size) noexcept - { - ... - } + struct FooAllocator + { + static void* Allocate(size_t size) noexcept + { + ... + } - static void Deallocate(void* ptr) noexcept - { - ... - } - }; + static void Deallocate(void* ptr) noexcept + { + ... + } + }; - class Foo : public Mso::UnknownObject, ISomeComInterface> - { - ... - }; + class Foo : public Mso::UnknownObject, + ISomeComInterface> + { + ... + }; - Mso::TCntPtr spFoo = Mso::Make(); + Mso::TCntPtr spFoo = Mso::Make(); - 12) A class that implements a COM interface with a custom stateful allocator. + 12) A class that implements a COM interface with a custom stateful allocator. - struct ICustomHeap - { - virtual void* Alloc(size_t size) noexcept = 0; - virtual void Free(void* ptr) noexcept = 0; - }; + struct ICustomHeap + { + virtual void* Alloc(size_t size) noexcept = 0; + virtual void Free(void* ptr) noexcept = 0; + }; - struct FooAllocator - { - static void* Allocate(size_t size, ICustomHeap* heap) noexcept - { - ... - } + struct FooAllocator + { + static void* Allocate(size_t size, ICustomHeap* heap) noexcept + { + ... + } - static void Deallocate(void* ptr) noexcept - { - ... - } - }; + static void Deallocate(void* ptr) noexcept + { + ... + } + }; - class Foo : public Mso::UnknownObject, ISomeComInterface> - { - ... - }; + class Foo : public Mso::UnknownObject, + ISomeComInterface> + { + ... + }; - ICustomHeap& heap = ...; - Mso::TCntPtr spFoo = Mso::Make(&heap); + ICustomHeap& heap = ...; + Mso::TCntPtr spFoo = Mso::Make(&heap); */ template -class DECLSPEC_NOVTABLE UnknownObject - : public Mso::QueryCastList +class DECLSPEC_NOVTABLE UnknownObject : public Mso::QueryCastList { - using Super = Mso::QueryCastList; + using Super = Mso::QueryCastList; public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" - using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. + using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" + using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(UnknownObject); + _MSO_OBJECT_SIMPLEREFCOUNT(UnknownObject); - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override - { - return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); - } + _Success_(return == S_OK) STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override + { + return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); + } - STDMETHOD_(ULONG, AddRef)() noexcept override - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x0110559f /* tag_befw5 */)); - } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x0110559f /* tag_befw5 */)); + } - return 1; - } + return 1; + } - STDMETHOD_(ULONG, Release)() noexcept override - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x011055a0 /* tag_befw6 */)); - if (refCount == 0) - { - RefCountPolicy::Delete(this); - } + STDMETHOD_(ULONG, Release)() noexcept override + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x011055a0 /* tag_befw6 */)); + if (refCount == 0) + { + RefCountPolicy::Delete(this); + } - return 1; - } + return 1; + } protected: - template - UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) {} + template + UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) + { + } - virtual ~UnknownObject() noexcept = default; + virtual ~UnknownObject() noexcept = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - template class DECLSPEC_NOVTABLE UnknownObject, TBaseType0, TBaseTypes...> - : public Mso::QueryCastList + : public Mso::QueryCastList { - using Super = Mso::QueryCastList; + using Super = Mso::QueryCastList; public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" - using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. + using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" + using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(UnknownObject); + _MSO_OBJECT_SIMPLEREFCOUNT(UnknownObject); - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) override - { - return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); - } + _Success_(return == S_OK) STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) override + { + return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); + } - STDMETHOD_(ULONG, AddRef)() override - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x011055a1 /* tag_befw7 */)); - } + STDMETHOD_(ULONG, AddRef)() override + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x011055a1 /* tag_befw7 */)); + } - return 1; - } + return 1; + } - STDMETHOD_(ULONG, Release)() override - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x011055a2 /* tag_befw8 */)); - if (refCount == 0) - { - TDeleter::Delete(this); - } + STDMETHOD_(ULONG, Release)() override + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x011055a2 /* tag_befw8 */)); + if (refCount == 0) + { + TDeleter::Delete(this); + } - return 1; - } + return 1; + } protected: - template - UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) {} + template + UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) + { + } - virtual ~UnknownObject() noexcept = default; + virtual ~UnknownObject() noexcept = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - template class DECLSPEC_NOVTABLE UnknownObject - : public TBaseType0 - , public TBaseTypes... + : public TBaseType0 + , public TBaseTypes... { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::SimpleRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::SimpleRefCountPolicy; + friend RefCountPolicy; - using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" - using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. + using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" + using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_SIMPLEREFCOUNT(UnknownObject); + _MSO_OBJECT_SIMPLEREFCOUNT(UnknownObject); - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override - { - return E_FAIL; - } + _Success_(return == S_OK) + STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override + { + return E_FAIL; + } - STDMETHOD_(ULONG, AddRef)() noexcept override - { - if (++m_refCount == 1) - { - Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x011055a3 /* tag_befw9 */)); - } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + if (++m_refCount == 1) + { + Debug(VerifyElseCrashSzTag(false, "Ref count must not bounce from zero", 0x011055a3 /* tag_befw9 */)); + } - return 1; - } + return 1; + } - STDMETHOD_(ULONG, Release)() noexcept override - { - const uint32_t refCount = --m_refCount; - Debug(VerifyElseCrashSzTag(static_cast(refCount) >= 0, "Ref count must not be negative.", 0x011055c0 /* tag_befxa */)); - if (refCount == 0) - { - RefCountPolicy::Delete(this); - } + STDMETHOD_(ULONG, Release)() noexcept override + { + const uint32_t refCount = --m_refCount; + Debug(VerifyElseCrashSzTag( + static_cast(refCount) >= 0, "Ref count must not be negative.", 0x011055c0 /* tag_befxa */)); + if (refCount == 0) + { + RefCountPolicy::Delete(this); + } - return 1; - } + return 1; + } protected: - template - UnknownObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) {} + template + UnknownObject(TArgs&&... args) noexcept : TBaseType0(std::forward(args)...) + { + } - virtual ~UnknownObject() noexcept = default; + virtual ~UnknownObject() noexcept = default; private: - mutable std::atomic m_refCount { 1 }; + mutable std::atomic m_refCount{1}; }; - template class UnknownObject, TBaseType0, TBaseTypes...> - : public Mso::QueryCastList + : public Mso::QueryCastList { - using Super = Mso::QueryCastList; + using Super = Mso::QueryCastList; public: - using MakePolicy = Mso::MakePolicy::NoThrowCtor; - using RefCountPolicy = Mso::WeakRefCountPolicy; - friend RefCountPolicy; + using MakePolicy = Mso::MakePolicy::NoThrowCtor; + using RefCountPolicy = Mso::WeakRefCountPolicy; + friend RefCountPolicy; - using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" - using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. + using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" + using TypeToDelete = UnknownObject; // To verify that TypeToDelete is the first in the inheritance chain. - _MSO_OBJECT_WEAKREFCOUNT(UnknownObject); + _MSO_OBJECT_WEAKREFCOUNT(UnknownObject); - void* QueryCast(const GUID& riid) noexcept - { - if (riid == __uuidof(ObjectWeakRef)) - { - return &GetWeakRef(); - } + void* QueryCast(const GUID& riid) noexcept + { + if (riid == __uuidof(ObjectWeakRef)) + { + return &GetWeakRef(); + } - return Super::QueryCast(riid); - } + return Super::QueryCast(riid); + } - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override - { - return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); - } + _Success_(return == S_OK) STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override + { + return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); + } - STDMETHOD_(ULONG, AddRef)() noexcept override - { - GetWeakRef().AddRef(); - return 1; - } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + GetWeakRef().AddRef(); + return 1; + } - STDMETHOD_(ULONG, Release)() noexcept override - { - GetWeakRef().Release(); - return 1; - } + STDMETHOD_(ULONG, Release)() noexcept override + { + GetWeakRef().Release(); + return 1; + } protected: - template - UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) {} + template + UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) + { + } - virtual ~UnknownObject() noexcept = default; + virtual ~UnknownObject() noexcept = default; }; template class DECLSPEC_NOVTABLE UnknownObject - : public Mso::QueryCastList + : public Mso::QueryCastList { - using Super = Mso::QueryCastList; + using Super = Mso::QueryCastList; public: - using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" + using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" - _MSO_OBJECT_NOREFCOUNT(UnknownObject); + _MSO_OBJECT_NOREFCOUNT(UnknownObject); - template - UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) {} + template + UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) + { + } - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override - { - return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); - } + _Success_(return == S_OK) STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override + { + return ::Mso::Details::QueryInterfaceHelper::QueryInterface(this, riid, ppvObject); + } - // Do not use override to support ISimpleUnknown interfaces - STDMETHOD_(ULONG, AddRef)() noexcept - { - return 1; - } + // Do not use override to support ISimpleUnknown interfaces + STDMETHOD_(ULONG, AddRef)() noexcept + { + return 1; + } - // Do not use override to support ISimpleUnknown interfaces - STDMETHOD_(ULONG, Release)() noexcept - { - return 1; - } + // Do not use override to support ISimpleUnknown interfaces + STDMETHOD_(ULONG, Release)() noexcept + { + return 1; + } - virtual ~UnknownObject() noexcept = default; + virtual ~UnknownObject() noexcept = default; }; - template class DECLSPEC_NOVTABLE UnknownObject - : public Mso::QueryCastList + : public Mso::QueryCastList { - using Super = Mso::QueryCastList; + using Super = Mso::QueryCastList; public: - using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" + using UnknownObjectType = UnknownObject; // To use in derived class as "using Super = UnknownObjectType" - _MSO_OBJECT_NOREFCOUNT(UnknownObject); + _MSO_OBJECT_NOREFCOUNT(UnknownObject); - template - UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) {} + template + UnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) + { + } - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override - { - return E_FAIL; - } + _Success_(return == S_OK) + STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override + { + return E_FAIL; + } - // Do not use override to support ISimpleUnknown interfaces - STDMETHOD_(ULONG, AddRef)() noexcept - { - return 1; - } + // Do not use override to support ISimpleUnknown interfaces + STDMETHOD_(ULONG, AddRef)() noexcept + { + return 1; + } - // Do not use override to support ISimpleUnknown interfaces - STDMETHOD_(ULONG, Release)() noexcept - { - return 1; - } + // Do not use override to support ISimpleUnknown interfaces + STDMETHOD_(ULONG, Release)() noexcept + { + return 1; + } - virtual ~UnknownObject()noexcept = default; + virtual ~UnknownObject() noexcept = default; }; - /** - A base class that supports a free threaded marshaler. + A base class that supports a free threaded marshaler. */ template -class AgileUnknownObject - : public UnknownObject +class AgileUnknownObject : public UnknownObject { - using Super = UnknownObject; + using Super = UnknownObject; public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(AgileUnknownObject); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(AgileUnknownObject); - template - AgileUnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) - { - } + template + AgileUnknownObject(TArgs&&... args) noexcept : Super(std::forward(args)...) + { + } - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override - { - HRESULT hr = Super::QueryInterface(riid, ppvObject); - if (hr == S_OK) - { - return hr; - } + _Success_(return == S_OK) STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override + { + HRESULT hr = Super::QueryInterface(riid, ppvObject); + if (hr == S_OK) + { + return hr; + } #if !defined(__clang__) && !defined(__GNUC__) - // Free threaded marshaler currently supported only for Windows and VC++ - if (riid == __uuidof(IMarshal) || riid == __uuidof(IAgileObject)) - { - if (m_ftm.IsEmpty()) - { - Mso::TCntPtr ftm; - VerifySucceededElseCrashTag(CoCreateFreeThreadedMarshaler(this->template StaticCastElseNull(), &ftm), 0x01003719 /* tag_bad2z */); - // Only assign ftm to m_ftm if its value is nullptr. Otherwise we will delete the new ftm and use the existing m_ftm. - if (InterlockedCompareExchangePointer((volatile PVOID *)m_ftm.GetRaw(), ftm.Get(), nullptr) == nullptr) - { - // Success: the object is now owned by the m_ftm. Make sure that ftm does not delete it. - ftm.Detach(); - } - } + // Free threaded marshaler currently supported only for Windows and VC++ + if (riid == __uuidof(IMarshal) || riid == __uuidof(IAgileObject)) + { + if (m_ftm.IsEmpty()) + { + Mso::TCntPtr ftm; + VerifySucceededElseCrashTag( + CoCreateFreeThreadedMarshaler(this->template StaticCastElseNull(), &ftm), + 0x01003719 /* tag_bad2z */); + // Only assign ftm to m_ftm if its value is nullptr. Otherwise we will delete the new ftm and use the existing + // m_ftm. + if (InterlockedCompareExchangePointer((volatile PVOID*)m_ftm.GetRaw(), ftm.Get(), nullptr) == nullptr) + { + // Success: the object is now owned by the m_ftm. Make sure that ftm does not delete it. + ftm.Detach(); + } + } - return m_ftm->QueryInterface(riid, ppvObject); - } + return m_ftm->QueryInterface(riid, ppvObject); + } #endif - return E_NOINTERFACE; - } + return E_NOINTERFACE; + } protected: - using AgileUnknownObjectType = AgileUnknownObject; + using AgileUnknownObjectType = AgileUnknownObject; private: - Mso::TCntPtr m_ftm; + Mso::TCntPtr m_ftm; }; } // namespace Mso diff --git a/libs/object/include/object/weakPtr.h b/libs/object/include/object/weakPtr.h index df383a9..d995299 100644 --- a/libs/object/include/object/weakPtr.h +++ b/libs/object/include/object/weakPtr.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Support for object lifetime management using ref counting. + Support for object lifetime management using ref counting. */ #pragma once @@ -11,361 +11,359 @@ namespace Mso { -template class WeakPtr; +template +class WeakPtr; namespace Details { class WeakPtrBase { public: - void Reset() noexcept - { - CheckedReleaseWeakRef(); - m_ptr = nullptr; - m_weakRef = nullptr; - } + void Reset() noexcept + { + CheckedReleaseWeakRef(); + m_ptr = nullptr; + m_weakRef = nullptr; + } - bool IsEmpty() const noexcept - { - return m_ptr == nullptr; - } + bool IsEmpty() const noexcept + { + return m_ptr == nullptr; + } - bool IsExpired() const noexcept - { - return !m_ptr || m_weakRef->IsExpired(); - } + bool IsExpired() const noexcept + { + return !m_ptr || m_weakRef->IsExpired(); + } - template - static Mso::ObjectWeakRef* GetWeakRef(_In_opt_ T* from) noexcept - { - return GetWeakRefCore(from, 0, 0); - } + template + static Mso::ObjectWeakRef* GetWeakRef(_In_opt_ T* from) noexcept + { + return GetWeakRefCore(from, 0, 0); + } protected: - enum { AttachTag = 0 }; + enum + { + AttachTag = 0 + }; - WeakPtrBase() noexcept - : m_ptr(nullptr) - , m_weakRef(nullptr) - { - } + WeakPtrBase() noexcept : m_ptr(nullptr), m_weakRef(nullptr) {} - WeakPtrBase(_In_opt_ void* ptr, _In_opt_ Mso::ObjectWeakRef* weakRef) noexcept - : m_ptr(ptr) - , m_weakRef(ptr ? weakRef : nullptr) - { - CheckedAddWeakRef(); - } + WeakPtrBase(_In_opt_ void* ptr, _In_opt_ Mso::ObjectWeakRef* weakRef) noexcept + : m_ptr(ptr), m_weakRef(ptr ? weakRef : nullptr) + { + CheckedAddWeakRef(); + } - WeakPtrBase(_In_opt_ void* ptr, _In_opt_ Mso::ObjectWeakRef* weakRef, int /*attachTag*/) noexcept - : m_ptr(ptr) - , m_weakRef(weakRef) - { - } + WeakPtrBase(_In_opt_ void* ptr, _In_opt_ Mso::ObjectWeakRef* weakRef, int /*attachTag*/) noexcept + : m_ptr(ptr), m_weakRef(weakRef) + { + } - ~WeakPtrBase() noexcept - { - CheckedReleaseWeakRef(); - } + ~WeakPtrBase() noexcept + { + CheckedReleaseWeakRef(); + } - void Assign(_In_opt_ void* ptr, _In_opt_ ObjectWeakRef* weakRef) noexcept - { - CheckedReleaseWeakRef(); - m_ptr = ptr; - m_weakRef = weakRef; - CheckedAddWeakRef(); - } + void Assign(_In_opt_ void* ptr, _In_opt_ ObjectWeakRef* weakRef) noexcept + { + CheckedReleaseWeakRef(); + m_ptr = ptr; + m_weakRef = weakRef; + CheckedAddWeakRef(); + } - void Assign(_In_opt_ void* ptr, _In_opt_ ObjectWeakRef* weakRef, int /*attachTag*/) noexcept - { - CheckedReleaseWeakRef(); - m_ptr = ptr; - m_weakRef = weakRef; - } + void Assign(_In_opt_ void* ptr, _In_opt_ ObjectWeakRef* weakRef, int /*attachTag*/) noexcept + { + CheckedReleaseWeakRef(); + m_ptr = ptr; + m_weakRef = weakRef; + } - bool IncrementRefCountIfNotZero() const noexcept - { - return m_weakRef && m_weakRef->IncrementRefCountIfNotZero(); - } + bool IncrementRefCountIfNotZero() const noexcept + { + return m_weakRef && m_weakRef->IncrementRefCountIfNotZero(); + } private: - void CheckedAddWeakRef() const noexcept - { - if (m_weakRef) m_weakRef->AddWeakRef(); - } - - void CheckedReleaseWeakRef() const noexcept - { - if (m_weakRef) m_weakRef->ReleaseWeakRef(); - } + void CheckedAddWeakRef() const noexcept + { + if (m_weakRef) + m_weakRef->AddWeakRef(); + } - // Called when T has GetWeakRef method. - template - static auto GetWeakRefCore(_In_opt_ T* from, int, int) noexcept -> decltype(&from->GetWeakRef()) - { - if (from) - { - Mso::ObjectWeakRef* result = &from->GetWeakRef(); - VerifyElseCrashSzTag(result, "GetWeakRef() returned null", 0x0100371a /* tag_bad20 */); - return result; - } + void CheckedReleaseWeakRef() const noexcept + { + if (m_weakRef) + m_weakRef->ReleaseWeakRef(); + } - return nullptr; - } + // Called when T has GetWeakRef method. + template + static auto GetWeakRefCore(_In_opt_ T* from, int, int) noexcept -> decltype(&from->GetWeakRef()) + { + if (from) + { + Mso::ObjectWeakRef* result = &from->GetWeakRef(); + VerifyElseCrashSzTag(result, "GetWeakRef() returned null", 0x0100371a /* tag_bad20 */); + return result; + } - // Called when T has QueryInterface method. - template - static auto GetWeakRefCore(_In_opt_ T* from, int, ...) noexcept -> decltype(from->QueryInterface(__uuidof(Mso::ObjectWeakRef), nullptr), (Mso::ObjectWeakRef*)nullptr) - { - if (from) - { - Mso::ObjectWeakRef* result = query_cast(from); - VerifyElseCrashSzTag(result, "query_cast() returned null", 0x0100371b /* tag_bad21 */); - return result; - } + return nullptr; + } - return nullptr; - } + // Called when T has QueryInterface method. + template + static auto GetWeakRefCore(_In_opt_ T* from, int, ...) noexcept + -> decltype(from->QueryInterface(__uuidof(Mso::ObjectWeakRef), nullptr), (Mso::ObjectWeakRef*)nullptr) + { + if (from) + { + Mso::ObjectWeakRef* result = query_cast(from); + VerifyElseCrashSzTag(result, "query_cast() returned null", 0x0100371b /* tag_bad21 */); + return result; + } - // Called when T does not have GetWeakRef method. - template - static Mso::ObjectWeakRef* GetWeakRefCore(_In_opt_ T* /*from*/, ...) noexcept - { - VerifyElseCrashSzTag(false, "Cannot get ObjectWeakRef for an object.", 0x0100371c /* tag_bad22 */); - return nullptr; - } + return nullptr; + } - friend const void* GetUnsafePtr(const WeakPtrBase& weakPtrBase) noexcept - { - return weakPtrBase.m_ptr; - } + // Called when T does not have GetWeakRef method. + template + static Mso::ObjectWeakRef* GetWeakRefCore(_In_opt_ T* /*from*/, ...) noexcept + { + VerifyElseCrashSzTag(false, "Cannot get ObjectWeakRef for an object.", 0x0100371c /* tag_bad22 */); + return nullptr; + } + + friend const void* GetUnsafePtr(const WeakPtrBase& weakPtrBase) noexcept + { + return weakPtrBase.m_ptr; + } private: - void* m_ptr; - Mso::ObjectWeakRef* m_weakRef; + void* m_ptr; + Mso::ObjectWeakRef* m_weakRef; - template friend class Mso::WeakPtr; + template + friend class Mso::WeakPtr; }; } // namespace Details /** - A weak pointer based on the ObjectWeakRef. - It has two pointers: a pointer to the ObjectWeakRef and a pointer to the object. - Having two pointers allow us to address the following scenarios: - - We do not want to do any casting when retrieving a strong pointer. - - Multiple objects share the same ObjectWeakRef. + A weak pointer based on the ObjectWeakRef. + It has two pointers: a pointer to the ObjectWeakRef and a pointer to the object. + Having two pointers allow us to address the following scenarios: + - We do not want to do any casting when retrieving a strong pointer. + - Multiple objects share the same ObjectWeakRef. */ template class WeakPtr final : public Details::WeakPtrBase { - using Super = Details::WeakPtrBase; + using Super = Details::WeakPtrBase; public: - WeakPtr() noexcept : Super() {} - WeakPtr(std::nullptr_t) noexcept : Super() {} + WeakPtr() noexcept : Super() {} + WeakPtr(std::nullptr_t) noexcept : Super() {} - WeakPtr(_In_opt_ T* from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept - : Super(from, weakRef ? weakRef : GetWeakRefCore(from, 0, 0)) - { - } + WeakPtr(_In_opt_ T* from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept + : Super(from, weakRef ? weakRef : GetWeakRefCore(from, 0, 0)) + { + } - template ::value>::type> - WeakPtr(_In_opt_ TOther* from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept - : Super(static_cast(from), weakRef ? weakRef : GetWeakRefCore(from, 0, 0)) - { - } + template ::value>::type> + WeakPtr(_In_opt_ TOther* from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept + : Super(static_cast(from), weakRef ? weakRef : GetWeakRefCore(from, 0, 0)) + { + } - WeakPtr(const Mso::TCntPtr& from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept - : Super(from.Get(), weakRef ? weakRef : GetWeakRefCore(from.Get(), 0, 0)) - { - } + WeakPtr(const Mso::TCntPtr& from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept + : Super(from.Get(), weakRef ? weakRef : GetWeakRefCore(from.Get(), 0, 0)) + { + } - template ::value>::type> - WeakPtr(const Mso::TCntPtr& from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept - : Super(static_cast(from.Get()), weakRef ? weakRef : GetWeakRefCore(from.Get(), 0, 0)) - { - } + template ::value>::type> + WeakPtr(const Mso::TCntPtr& from, _In_opt_ Mso::ObjectWeakRef* weakRef = nullptr) noexcept + : Super(static_cast(from.Get()), weakRef ? weakRef : GetWeakRefCore(from.Get(), 0, 0)) + { + } - WeakPtr(const WeakPtr& from) noexcept - : Super(from.m_ptr, from.m_weakRef) - { - } + WeakPtr(const WeakPtr& from) noexcept : Super(from.m_ptr, from.m_weakRef) {} - template ::value>::type> - WeakPtr(const WeakPtr& from) noexcept - : Super(static_cast(static_cast(from.m_ptr)), from.m_weakRef) - { - } + template ::value>::type> + WeakPtr(const WeakPtr& from) noexcept + : Super(static_cast(static_cast(from.m_ptr)), from.m_weakRef) + { + } - WeakPtr(WeakPtr&& from) noexcept - : Super(from.m_ptr, from.m_weakRef, AttachTag) - { - from.m_ptr = nullptr; - from.m_weakRef = nullptr; - } + WeakPtr(WeakPtr&& from) noexcept : Super(from.m_ptr, from.m_weakRef, AttachTag) + { + from.m_ptr = nullptr; + from.m_weakRef = nullptr; + } - template ::value>::type> - WeakPtr(WeakPtr&& from) noexcept - : Super(static_cast(static_cast(from.m_ptr)), from.m_weakRef, AttachTag) - { - from.m_ptr = nullptr; - from.m_weakRef = nullptr; - } + template ::value>::type> + WeakPtr(WeakPtr&& from) noexcept + : Super(static_cast(static_cast(from.m_ptr)), from.m_weakRef, AttachTag) + { + from.m_ptr = nullptr; + from.m_weakRef = nullptr; + } - WeakPtr& operator=(std::nullptr_t) noexcept - { - Reset(); - return *this; - } + WeakPtr& operator=(std::nullptr_t) noexcept + { + Reset(); + return *this; + } - WeakPtr& operator=(_In_opt_ T* from) noexcept - { - if (m_ptr != from) - { - Assign(from, GetWeakRefCore(from, 0, 0)); - } + WeakPtr& operator=(_In_opt_ T* from) noexcept + { + if (m_ptr != from) + { + Assign(from, GetWeakRefCore(from, 0, 0)); + } - return *this; - } + return *this; + } - template ::value>::type> - WeakPtr& operator=(_In_opt_ TOther* from) noexcept - { - T* ptr = static_cast(from); - if (m_ptr != ptr) - { - Assign(ptr, GetWeakRefCore(from, 0, 0)); - } + template ::value>::type> + WeakPtr& operator=(_In_opt_ TOther* from) noexcept + { + T* ptr = static_cast(from); + if (m_ptr != ptr) + { + Assign(ptr, GetWeakRefCore(from, 0, 0)); + } - return *this; - } + return *this; + } - WeakPtr& operator=(const Mso::TCntPtr& from) noexcept - { - T* ptr = from.Get(); - if (m_ptr != ptr) - { - Assign(ptr, GetWeakRefCore(ptr, 0, 0)); - } + WeakPtr& operator=(const Mso::TCntPtr& from) noexcept + { + T* ptr = from.Get(); + if (m_ptr != ptr) + { + Assign(ptr, GetWeakRefCore(ptr, 0, 0)); + } - return *this; - } + return *this; + } - template ::value>::type> - WeakPtr& operator=(const Mso::TCntPtr& from) noexcept - { - TOther* otherPtr = from.Get(); - T* ptr = static_cast(otherPtr); - if (m_ptr != ptr) - { - Assign(ptr, GetWeakRefCore(otherPtr, 0, 0)); - } + template ::value>::type> + WeakPtr& operator=(const Mso::TCntPtr& from) noexcept + { + TOther* otherPtr = from.Get(); + T* ptr = static_cast(otherPtr); + if (m_ptr != ptr) + { + Assign(ptr, GetWeakRefCore(otherPtr, 0, 0)); + } - return *this; - } + return *this; + } - WeakPtr& operator=(const WeakPtr& from) noexcept - { - if (m_ptr != from.m_ptr) - { - Assign(from.m_ptr, from.m_weakRef); - } + WeakPtr& operator=(const WeakPtr& from) noexcept + { + if (m_ptr != from.m_ptr) + { + Assign(from.m_ptr, from.m_weakRef); + } - return *this; - } + return *this; + } - template ::value>::type> - WeakPtr& operator=(const WeakPtr& from) noexcept - { - T* ptr = static_cast(static_cast(from.m_ptr)); - if (m_ptr != ptr) - { - Assign(ptr, from.m_weakRef); - } + template ::value>::type> + WeakPtr& operator=(const WeakPtr& from) noexcept + { + T* ptr = static_cast(static_cast(from.m_ptr)); + if (m_ptr != ptr) + { + Assign(ptr, from.m_weakRef); + } - return *this; - } + return *this; + } - WeakPtr& operator=(WeakPtr&& from) noexcept - { - if (m_ptr != from.m_ptr) - { - Assign(from.m_ptr, from.m_weakRef, AttachTag); - from.m_ptr = nullptr; - from.m_weakRef = nullptr; - } + WeakPtr& operator=(WeakPtr&& from) noexcept + { + if (m_ptr != from.m_ptr) + { + Assign(from.m_ptr, from.m_weakRef, AttachTag); + from.m_ptr = nullptr; + from.m_weakRef = nullptr; + } - return *this; - } + return *this; + } - template ::value>::type> - WeakPtr& operator=(WeakPtr&& from) noexcept - { - T* ptr = static_cast(static_cast(from.m_ptr)); - if (m_ptr != ptr) - { - Assign(ptr, from.m_weakRef, AttachTag); - from.m_ptr = nullptr; - from.m_weakRef = nullptr; - } + template ::value>::type> + WeakPtr& operator=(WeakPtr&& from) noexcept + { + T* ptr = static_cast(static_cast(from.m_ptr)); + if (m_ptr != ptr) + { + Assign(ptr, from.m_weakRef, AttachTag); + from.m_ptr = nullptr; + from.m_weakRef = nullptr; + } - return *this; - } + return *this; + } - Mso::TCntPtr GetStrongPtr() const noexcept - { - Mso::TCntPtr ptr; - if (IncrementRefCountIfNotZero()) - { - *ptr.GetRaw() = static_cast(m_ptr); - } + Mso::TCntPtr GetStrongPtr() const noexcept + { + Mso::TCntPtr ptr; + if (IncrementRefCountIfNotZero()) + { + *ptr.GetRaw() = static_cast(m_ptr); + } - return ptr; - } + return ptr; + } - void Swap(WeakPtr& other) noexcept - { - using std::swap; - std::swap(m_ptr, other.m_ptr); - std::swap(m_weakRef, other.m_weakRef); - } + void Swap(WeakPtr& other) noexcept + { + using std::swap; + std::swap(m_ptr, other.m_ptr); + std::swap(m_weakRef, other.m_weakRef); + } }; template bool operator==(const WeakPtr& left, const WeakPtr& right) noexcept { - return GetUnsafePtr(left) == GetUnsafePtr(right); + return GetUnsafePtr(left) == GetUnsafePtr(right); } template bool operator==(const WeakPtr& left, std::nullptr_t) noexcept { - return left.IsEmpty(); + return left.IsEmpty(); } template bool operator==(std::nullptr_t, const WeakPtr& right) noexcept { - return right.IsEmpty(); + return right.IsEmpty(); } template bool operator!=(const WeakPtr& left, const WeakPtr& right) noexcept { - return GetUnsafePtr(left) != GetUnsafePtr(right); + return GetUnsafePtr(left) != GetUnsafePtr(right); } template bool operator!=(const WeakPtr& left, std::nullptr_t) noexcept { - return !left.IsEmpty(); + return !left.IsEmpty(); } template bool operator!=(std::nullptr_t, const WeakPtr& right) noexcept { - return !right.IsEmpty(); + return !right.IsEmpty(); } } // namespace Mso diff --git a/libs/object/tests/TCntPtrRefTest.cpp b/libs/object/tests/TCntPtrRefTest.cpp index eb59539..e14db75 100644 --- a/libs/object/tests/TCntPtrRefTest.cpp +++ b/libs/object/tests/TCntPtrRefTest.cpp @@ -16,177 +16,189 @@ Unit tests for the TCntPtrRef class MSO_STRUCT_GUID(ISimpleUnknown, "C70B7853-1EDB-4AB8-B2D2-F9951A99A847") struct DECLSPEC_NOVTABLE ISimpleUnknown : public IUnknown { - virtual void DoSomething() = 0; + virtual void DoSomething() = 0; }; struct ISimple : public Mso::IRefCounted { - virtual void DoSomething() = 0; + virtual void DoSomething() = 0; }; class SimpleTestRef : public Mso::TRefCountedImpl { - void DoSomething() override {} + void DoSomething() override {} }; -inline static std::wstring ToString(ISimple* q) { return L""; } -inline static std::wstring ToString(ISimple** q) { return L""; } -inline static std::wstring ToString(const ISimple* q) { return L""; } -inline static std::wstring ToString(ISimple* const* q) { return L""; } -inline static std::wstring ToString(const Mso::TCntPtr* q) { return L""; } - -TestClassComponent(TCntPtrRefTest, Mso.TCntPtrRef) -TEST_CLASS(TCntPtrRefTest) +inline static std::wstring ToString(ISimple* q) { - -TEST_METHOD(TCntPtr_TCntPtrRef_GetRaw) + return L""; +} +inline static std::wstring ToString(ISimple** q) { - Mso::TCntPtr spObj; - TestAssert::AreEqual(spObj.GetRaw(), (&spObj).GetRaw()); + return L""; +} +inline static std::wstring ToString(const ISimple* q) +{ + return L""; +} +inline static std::wstring ToString(ISimple* const* q) +{ + return L""; +} +inline static std::wstring ToString(const Mso::TCntPtr* q) +{ + return L""; } -TEST_METHOD(TCntPtr_TCntPtrRef_StarOperator) +TestClassComponent(TCntPtrRefTest, Mso.TCntPtrRef) TEST_CLASS (TCntPtrRefTest) { - Mso::TCntPtr spObj; - TestAssert::AreEqual(spObj.Get(), *(&spObj)); -} + TEST_METHOD(TCntPtr_TCntPtrRef_GetRaw) + { + Mso::TCntPtr spObj; + TestAssert::AreEqual(spObj.GetRaw(), (&spObj).GetRaw()); + } -TEST_METHOD(TCntPtr_TCntPtrRef_GetAddressOf) -{ - Mso::TCntPtr spObj; - TestAssert::AreEqual(spObj.GetAddressOf(), const_cast((&spObj).GetAddressOf())); -} + TEST_METHOD(TCntPtr_TCntPtrRef_StarOperator) + { + Mso::TCntPtr spObj; + TestAssert::AreEqual(spObj.Get(), *(&spObj)); + } -TEST_METHOD(TCntPtr_TCntPtrRef_ClearAndGetAddressOf) -{ - Mso::TCntPtr spObj = new SimpleTestRef(); - TestAssert::AreEqual(spObj.GetRaw(), (&spObj).ClearAndGetAddressOf()); - TestAssert::IsNull(spObj.Get()); -} + TEST_METHOD(TCntPtr_TCntPtrRef_GetAddressOf) + { + Mso::TCntPtr spObj; + TestAssert::AreEqual(spObj.GetAddressOf(), const_cast((&spObj).GetAddressOf())); + } -TEST_METHOD(TCntPtr_TCntPtrRef_IID_PPV_ARGS_Helper) -{ - Mso::TCntPtr spObj; - void** ppObj = IID_PPV_ARGS_Helper(&spObj); - void** ppDesired = &spObj; - TestAssert::AreEqual((void*)ppDesired, (void*)ppObj); -} + TEST_METHOD(TCntPtr_TCntPtrRef_ClearAndGetAddressOf) + { + Mso::TCntPtr spObj = new SimpleTestRef(); + TestAssert::AreEqual(spObj.GetRaw(), (&spObj).ClearAndGetAddressOf()); + TestAssert::IsNull(spObj.Get()); + } -TEST_METHOD(TCntPtr_TCntPtrRef_EqualOperator) -{ - Mso::TCntPtr spObj1; - Mso::TCntPtr spObj2; - TestAssert::IsTrue(&spObj1 == &spObj1); - TestAssert::IsTrue(&spObj2 == &spObj2); - TestAssert::IsFalse(&spObj1 == &spObj2); - TestAssert::IsFalse(&spObj2 == &spObj1); -} + TEST_METHOD(TCntPtr_TCntPtrRef_IID_PPV_ARGS_Helper) + { + Mso::TCntPtr spObj; + void** ppObj = IID_PPV_ARGS_Helper(&spObj); + void** ppDesired = &spObj; + TestAssert::AreEqual((void*)ppDesired, (void*)ppObj); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NotEqualOperator) -{ - Mso::TCntPtr spObj1; - Mso::TCntPtr spObj2; - TestAssert::IsTrue(&spObj1 != &spObj2); - TestAssert::IsTrue(&spObj2 != &spObj1); - TestAssert::IsFalse(&spObj2 != &spObj2); - TestAssert::IsFalse(&spObj1 != &spObj1); -} + TEST_METHOD(TCntPtr_TCntPtrRef_EqualOperator) + { + Mso::TCntPtr spObj1; + Mso::TCntPtr spObj2; + TestAssert::IsTrue(&spObj1 == &spObj1); + TestAssert::IsTrue(&spObj2 == &spObj2); + TestAssert::IsFalse(&spObj1 == &spObj2); + TestAssert::IsFalse(&spObj2 == &spObj1); + } -static void TestFunc1(_In_ _Notnull_ ISimple* pObj, _Out_ ISimple** ppObj) -{ - *ppObj = pObj; -} + TEST_METHOD(TCntPtr_TCntPtrRef_NotEqualOperator) + { + Mso::TCntPtr spObj1; + Mso::TCntPtr spObj2; + TestAssert::IsTrue(&spObj1 != &spObj2); + TestAssert::IsTrue(&spObj2 != &spObj1); + TestAssert::IsFalse(&spObj2 != &spObj2); + TestAssert::IsFalse(&spObj1 != &spObj1); + } -static void TestFunc2(_In_ _Notnull_ ISimple* pObj, _Out_ Mso::TCntPtr* spObj) -{ - *spObj = Mso::TCntPtr(pObj, false); -} + static void TestFunc1(_In_ _Notnull_ ISimple * pObj, _Out_ ISimple * *ppObj) + { + *ppObj = pObj; + } -static void TestFunc3(_In_ _Notnull_ ISimple* pObj, _Out_ void** ppT) -{ - *ppT = pObj; -} + static void TestFunc2(_In_ _Notnull_ ISimple * pObj, _Out_ Mso::TCntPtr * spObj) + { + *spObj = Mso::TCntPtr(pObj, false); + } -static void TestFunc4(_In_ _Notnull_ const ISimple* pObj, _Out_ const void** ppT) -{ - *ppT = pObj; -} + static void TestFunc3(_In_ _Notnull_ ISimple * pObj, _Out_ void** ppT) + { + *ppT = pObj; + } -template -static void TestTCntPtrRef(U&& func) -{ - T spObjOutput; - Mso::TCntPtr spObjInput = new SimpleTestRef(); - ISimple* pObjInput = spObjInput.Detach(); + static void TestFunc4(_In_ _Notnull_ const ISimple* pObj, _Out_ const void** ppT) + { + *ppT = pObj; + } - func(pObjInput, &spObjOutput); + template + static void TestTCntPtrRef(U && func) + { + T spObjOutput; + Mso::TCntPtr spObjInput = new SimpleTestRef(); + ISimple* pObjInput = spObjInput.Detach(); - TestAssert::AreEqual(pObjInput, spObjOutput.Get()); -} + func(pObjInput, &spObjOutput); -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_ppT) -{ - TestTCntPtrRef>(TestFunc1); -} + TestAssert::AreEqual(pObjInput, spObjOutput.Get()); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_pTCntPtr) -{ - TestTCntPtrRef>(TestFunc2); -} + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_ppT) + { + TestTCntPtrRef>(TestFunc1); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_ppVoid) -{ - TestTCntPtrRef>(TestFunc3); -} + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_pTCntPtr) + { + TestTCntPtrRef>(TestFunc2); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_ppConstVoid) -{ - TestTCntPtrRef>(TestFunc4); -} + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_ppVoid) + { + TestTCntPtrRef>(TestFunc3); + } -TEST_METHOD(TCntPtr_TCntPtrRef_Const_TCntPtr) -{ - const Mso::TCntPtr spObj; - TestAssert::AreEqual(spObj.GetThis(), &spObj); -} + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_ppConstVoid) + { + TestTCntPtrRef>(TestFunc4); + } -template -static void TestTCntPtrRef_Reinterpret_Cast() -{ - using TNonConst = typename std::remove_const::type; - T spObj; - U ppObjDesired = reinterpret_cast(const_cast(spObj).GetAddressOf()); - U ppObj = static_cast(&spObj); - TestAssert::AreEqual((void*)ppObjDesired, (void*)ppObj); -} + TEST_METHOD(TCntPtr_TCntPtrRef_Const_TCntPtr) + { + const Mso::TCntPtr spObj; + TestAssert::AreEqual(spObj.GetThis(), &spObj); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_Reinterpret_Cast_ppVoid) -{ - TestTCntPtrRef_Reinterpret_Cast, void**>(); -} + template + static void TestTCntPtrRef_Reinterpret_Cast() + { + using TNonConst = typename std::remove_const::type; + T spObj; + U ppObjDesired = reinterpret_cast(const_cast(spObj).GetAddressOf()); + U ppObj = static_cast(&spObj); + TestAssert::AreEqual((void*)ppObjDesired, (void*)ppObj); + } -class SimpleTestRefUnknown : public Mso::UnknownObject -{ - void DoSomething() override {} -}; + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_Reinterpret_Cast_ppVoid) + { + TestTCntPtrRef_Reinterpret_Cast, void**>(); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_Reinterpret_Cast_ppIUnknown) -{ - TestTCntPtrRef_Reinterpret_Cast, IUnknown**>(); -} + class SimpleTestRefUnknown : public Mso::UnknownObject + { + void DoSomething() override {} + }; -template -static void TestTCntPtrRef_Cast_pVoid() -{ - T spObj; - void* pVoid = &spObj; - Mso::TCntPtr* pTCntPtr = &spObj; - TestAssert::AreEqual(pVoid, (void*)pTCntPtr); -} + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_Reinterpret_Cast_ppIUnknown) + { + TestTCntPtrRef_Reinterpret_Cast, IUnknown**>(); + } -TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_Cast_pVoid) -{ - TestTCntPtrRef_Cast_pVoid>(); -} + template + static void TestTCntPtrRef_Cast_pVoid() + { + T spObj; + void* pVoid = &spObj; + Mso::TCntPtr* pTCntPtr = &spObj; + TestAssert::AreEqual(pVoid, (void*)pTCntPtr); + } + TEST_METHOD(TCntPtr_TCntPtrRef_NonConst_Cast_pVoid) + { + TestTCntPtrRef_Cast_pVoid>(); + } }; \ No newline at end of file diff --git a/libs/object/tests/TCntPtrTest.cpp b/libs/object/tests/TCntPtrTest.cpp index bb54bd9..aebee2d 100644 --- a/libs/object/tests/TCntPtrTest.cpp +++ b/libs/object/tests/TCntPtrTest.cpp @@ -15,430 +15,411 @@ Unit tests for the TCntPtr smart pointer MSO_STRUCT_GUID(IUnkSimple, "9FEAB33F-E5D0-4A52-9216-6BA8BA9990A4") struct IUnkSimple : public IUnknown { - virtual void DoSomething() = 0; + virtual void DoSomething() = 0; }; MSO_STRUCT_GUID(IUnkSample, "8A2560F5-E28D-4342-8716-1BBD3A4603B3") struct IUnkSample : public IUnknown { - virtual void DoAnything() = 0; + virtual void DoAnything() = 0; }; struct ISimple : public Mso::IRefCounted { - virtual void DoSomething() = 0; + virtual void DoSomething() = 0; }; typedef std::function RefCountChangedCallback; class SimpleClass : public ISimple { public: - SimpleClass(RefCountChangedCallback&& onRefCountChanged) - : m_refCount(0) - , m_onRefCountChanged(std::move(onRefCountChanged)) - { - } + SimpleClass(RefCountChangedCallback&& onRefCountChanged) + : m_refCount(0), m_onRefCountChanged(std::move(onRefCountChanged)) + { + } - virtual void AddRef() const noexcept override - { - OACR_ASSUME_NOTHROW_BEGIN + virtual void AddRef() const noexcept override + { + OACR_ASSUME_NOTHROW_BEGIN - m_onRefCountChanged(/*incremented*/true); + m_onRefCountChanged(/*incremented*/ true); - OACR_ASSUME_NOTHROW_END + OACR_ASSUME_NOTHROW_END - ++m_refCount; - } + ++m_refCount; + } - virtual void Release() const noexcept override - { - OACR_ASSUME_NOTHROW_BEGIN + virtual void Release() const noexcept override + { + OACR_ASSUME_NOTHROW_BEGIN - m_onRefCountChanged(/*incremented*/false); + m_onRefCountChanged(/*incremented*/ false); - OACR_ASSUME_NOTHROW_END + OACR_ASSUME_NOTHROW_END - if (--m_refCount == 0) - { - delete this; - } - } + if (--m_refCount == 0) + { + delete this; + } + } - virtual void DoSomething() noexcept override - { - } + virtual void DoSomething() noexcept override {} - void ClassDoSomething() noexcept - { - OACR_USE_PTR(this); // simulates access to 'this' for OACR build - } + void ClassDoSomething() noexcept + { + OACR_USE_PTR(this); // simulates access to 'this' for OACR build + } private: - mutable std::atomic m_refCount; - RefCountChangedCallback m_onRefCountChanged; + mutable std::atomic m_refCount; + RefCountChangedCallback m_onRefCountChanged; }; class UnkSimpleClass : public IUnkSimple { public: - UnkSimpleClass(RefCountChangedCallback&& onRefCountChanged) - : m_refCount(0) - , m_onRefCountChanged(std::move(onRefCountChanged)) - { - } + UnkSimpleClass(RefCountChangedCallback&& onRefCountChanged) + : m_refCount(0), m_onRefCountChanged(std::move(onRefCountChanged)) + { + } - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override - { - return E_NOINTERFACE; - } + _Success_(return == S_OK) + STDMETHOD(QueryInterface)(const GUID& /*riid*/, _Outptr_ void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } - STDMETHOD_(ULONG, AddRef)() noexcept override - { - OACR_ASSUME_NOTHROW_BEGIN - m_onRefCountChanged(/*incremented*/true); - OACR_ASSUME_NOTHROW_END - ++m_refCount; - return 1; - } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + OACR_ASSUME_NOTHROW_BEGIN + m_onRefCountChanged(/*incremented*/ true); + OACR_ASSUME_NOTHROW_END + ++m_refCount; + return 1; + } - STDMETHOD_(ULONG, Release)() noexcept override - { - OACR_ASSUME_NOTHROW_BEGIN - m_onRefCountChanged(/*incremented*/false); - OACR_ASSUME_NOTHROW_END - if (--m_refCount == 0) - { - delete this; - } + STDMETHOD_(ULONG, Release)() noexcept override + { + OACR_ASSUME_NOTHROW_BEGIN + m_onRefCountChanged(/*incremented*/ false); + OACR_ASSUME_NOTHROW_END + if (--m_refCount == 0) + { + delete this; + } - return 1; - } + return 1; + } - virtual void DoSomething() noexcept override - { - } + virtual void DoSomething() noexcept override {} - void ClassDoSomething() noexcept - { - OACR_USE_PTR(this); // simulates access to 'this' for OACR build - } + void ClassDoSomething() noexcept + { + OACR_USE_PTR(this); // simulates access to 'this' for OACR build + } private: - mutable std::atomic m_refCount; - RefCountChangedCallback m_onRefCountChanged; + mutable std::atomic m_refCount; + RefCountChangedCallback m_onRefCountChanged; }; -inline static std::wstring ToString(UnkSimpleClass* q) { return L""; } -inline static std::wstring ToString(SimpleClass* q) { return L""; } -inline static std::wstring ToString(const UnkSimpleClass* q) { return L""; } -inline static std::wstring ToString(const SimpleClass* q) { return L""; } +inline static std::wstring ToString(UnkSimpleClass* q) +{ + return L""; +} +inline static std::wstring ToString(SimpleClass* q) +{ + return L""; +} +inline static std::wstring ToString(const UnkSimpleClass* q) +{ + return L""; +} +inline static std::wstring ToString(const SimpleClass* q) +{ + return L""; +} class AggregatedObject : public Mso::UnknownObject { public: - virtual void DoSomething() noexcept override - { - } + virtual void DoSomething() noexcept override {} - virtual void DoAnything() noexcept override - { - } + virtual void DoAnything() noexcept override {} }; template static void ValidateRefCount(uint32_t expectedIncRefCountCallCount, TAction action) { - uint32_t actualIncRefCountCallCount = 0; - uint32_t actualDecRefCountCallCount = 0; - auto callback = [&actualIncRefCountCallCount, &actualDecRefCountCallCount](bool incremented) noexcept - { - if (incremented) - { - ++actualIncRefCountCallCount; - } - else - { - ++actualDecRefCountCallCount; - } - }; + uint32_t actualIncRefCountCallCount = 0; + uint32_t actualDecRefCountCallCount = 0; + auto callback = [&actualIncRefCountCallCount, &actualDecRefCountCallCount](bool incremented) noexcept { + if (incremented) + { + ++actualIncRefCountCallCount; + } + else + { + ++actualDecRefCountCallCount; + } + }; - action(RefCountChangedCallback(callback)); + action(RefCountChangedCallback(callback)); - TestAssert::AreEqual(actualIncRefCountCallCount, actualDecRefCountCallCount, L"IncCount != DecCount."); - TestAssert::AreEqual(expectedIncRefCountCallCount, actualIncRefCountCallCount, L"Unexpected IncCount."); + TestAssert::AreEqual(actualIncRefCountCallCount, actualDecRefCountCallCount, L"IncCount != DecCount."); + TestAssert::AreEqual(expectedIncRefCountCallCount, actualIncRefCountCallCount, L"Unexpected IncCount."); } -TestClassComponent(TCntPtrTest, Mso.TCntPtr) -TEST_CLASS(TCntPtrTest) -{ +TestClassComponent(TCntPtrTest, Mso.TCntPtr) TEST_CLASS (TCntPtrTest){ -TEST_METHOD(TCntPtr_EmptyCtor) -{ - Mso::TCntPtr spObj; + TEST_METHOD(TCntPtr_EmptyCtor){Mso::TCntPtr spObj; - TestAssert::IsNull(spObj.Get(), L"Expected null"); +TestAssert::IsNull(spObj.Get(), L"Expected null"); } TEST_METHOD(TCntPtr_NullCtor) { - Mso::TCntPtr spObj = nullptr; + Mso::TCntPtr spObj = nullptr; - TestAssert::IsNull(spObj.Get(), L"Expected null"); + TestAssert::IsNull(spObj.Get(), L"Expected null"); } TEST_METHOD(TCntPtr_DeprecatedNullCtor) { - //TODO: Remove when we stop using NULL - Mso::TCntPtr spObj; + // TODO: Remove when we stop using NULL + Mso::TCntPtr spObj; - TestAssert::IsNull(spObj.Get(), L"Expected null"); + TestAssert::IsNull(spObj.Get(), L"Expected null"); } TEST_METHOD(TCntPtr_Create) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); - TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_CreateInterface) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spIntf(ptr); + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spIntf(ptr); - TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_CopyConstructor) { - ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - Mso::TCntPtr spSameObj(spObj); + ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + Mso::TCntPtr spSameObj(spObj); - TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); - TestAssert::AreEqual((void*)ptr, (void*)spSameObj.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); + TestAssert::AreEqual((void*)ptr, (void*)spSameObj.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_CopyConstructorInterface) { - ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - Mso::TCntPtr spIntf(spObj); + ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + Mso::TCntPtr spIntf(spObj); - TestAssert::AreEqual((void*) ptr, (void*) spObj.Get(), L"Expected ptr"); - TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); + TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_MoveConstructor) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - Mso::TCntPtr spSameObj(std::move(spObj)); + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + Mso::TCntPtr spSameObj(std::move(spObj)); - TestAssert::IsNull(spObj.Get(), L"Expected null"); - TestAssert::AreEqual((void*)ptr, (void*)spSameObj.Get(), L"Expected ptr"); - }); + TestAssert::IsNull(spObj.Get(), L"Expected null"); + TestAssert::AreEqual((void*)ptr, (void*)spSameObj.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_MoveConstructorInterface) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - Mso::TCntPtr spIntf(std::move(spObj)); + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + Mso::TCntPtr spIntf(std::move(spObj)); - TestAssert::IsNull(spObj.Get(), L"Expected null"); - TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); - }); + TestAssert::IsNull(spObj.Get(), L"Expected null"); + TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); + }); } // Factory method to get benefits from using the move constructor static Mso::TCntPtr CreateSimpleClass(RefCountChangedCallback&& onRefCountChanged) { - Mso::TCntPtr spObj = new SimpleClass(std::move(onRefCountChanged)); - spObj->ClassDoSomething(); - return spObj; // std::move() not needed because the same type allows the named return value optimization. + Mso::TCntPtr spObj = new SimpleClass(std::move(onRefCountChanged)); + spObj->ClassDoSomething(); + return spObj; // std::move() not needed because the same type allows the named return value optimization. } TEST_METHOD(TCntPtr_CallCreateSimpleClass) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - Mso::TCntPtr spObj = CreateSimpleClass(std::move(onRefCountChanged)); + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + Mso::TCntPtr spObj = CreateSimpleClass(std::move(onRefCountChanged)); - TestAssert::IsNotNull(spObj.Get(), L"Expected not a null value"); - }); + TestAssert::IsNotNull(spObj.Get(), L"Expected not a null value"); + }); } // Factory method to get benefits from using the move constructor static Mso::TCntPtr CreateISimple(RefCountChangedCallback&& onRefCountChanged) { - Mso::TCntPtr spObj = new SimpleClass(std::move(onRefCountChanged)); - spObj->ClassDoSomething(); - return std::move(spObj); // We should use std::move() here to avoid use of copy constructor. - // Named value return optimization will not work because we have different types. + Mso::TCntPtr spObj = new SimpleClass(std::move(onRefCountChanged)); + spObj->ClassDoSomething(); + return std::move(spObj); // We should use std::move() here to avoid use of copy constructor. + // Named value return optimization will not work because we have different types. } TEST_METHOD(TCntPtr_CallCreateISimple) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - Mso::TCntPtr spIntf = CreateISimple(std::move(onRefCountChanged)); + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + Mso::TCntPtr spIntf = CreateISimple(std::move(onRefCountChanged)); - TestAssert::IsNotNull(spIntf.Get(), L"Expected not a null value"); - }); + TestAssert::IsNotNull(spIntf.Get(), L"Expected not a null value"); + }); } TEST_METHOD(TCntPtr_CopyAssignment) { - ValidateRefCount(3, [](RefCountChangedCallback&& onRefCountChanged) - { - Mso::TCntPtr spObj1(new SimpleClass(RefCountChangedCallback(onRefCountChanged))); - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj2(ptr); - spObj1 = spObj2; + ValidateRefCount(3, [](RefCountChangedCallback&& onRefCountChanged) { + Mso::TCntPtr spObj1(new SimpleClass(RefCountChangedCallback(onRefCountChanged))); + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj2(ptr); + spObj1 = spObj2; - TestAssert::AreEqual((void*)ptr, (void*)spObj1.Get(), L"Expected ptr"); - TestAssert::AreEqual((void*)ptr, (void*)spObj2.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj1.Get(), L"Expected ptr"); + TestAssert::AreEqual((void*)ptr, (void*)spObj2.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_CopyAssignmentInterface) { - ValidateRefCount(3, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - Mso::TCntPtr spIntf = new SimpleClass(std::move(onRefCountChanged)); - spIntf = spObj; + ValidateRefCount(3, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + Mso::TCntPtr spIntf = new SimpleClass(std::move(onRefCountChanged)); + spIntf = spObj; - TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); - TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); + TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_CopyAssignmentSameObject) { - // See what happens when we assign TCntPtr to itself. - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); + // See what happens when we assign TCntPtr to itself. + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); - OACR_WARNING_SUPPRESS(IDENTITY_ASSIGNMENT, "We want to test our code that nothing bad happens in this case"); - spObj = spObj; + OACR_WARNING_SUPPRESS(IDENTITY_ASSIGNMENT, "We want to test our code that nothing bad happens in this case"); + spObj = spObj; - TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_CopyAssignmentConst) { - // Test that TCntPtr can accept a const variable and AddRef/Release methods are not const. - ValidateRefCount(3, [](RefCountChangedCallback&& onRefCountChanged) - { - Mso::TCntPtr spObj1(new UnkSimpleClass(RefCountChangedCallback(onRefCountChanged))); - const UnkSimpleClass* ptr = new UnkSimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj2(ptr); - spObj1 = spObj2; + // Test that TCntPtr can accept a const variable and AddRef/Release methods are not const. + ValidateRefCount(3, [](RefCountChangedCallback&& onRefCountChanged) { + Mso::TCntPtr spObj1(new UnkSimpleClass(RefCountChangedCallback(onRefCountChanged))); + const UnkSimpleClass* ptr = new UnkSimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj2(ptr); + spObj1 = spObj2; - TestAssert::AreEqual((void*)ptr, (void*)spObj1.Get(), L"Expected ptr"); - TestAssert::AreEqual((void*)ptr, (void*)spObj2.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj1.Get(), L"Expected ptr"); + TestAssert::AreEqual((void*)ptr, (void*)spObj2.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_MoveAssignment) { - ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) - { - Mso::TCntPtr spObj1 = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj2(ptr); - spObj1 = std::move(spObj2); + ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) { + Mso::TCntPtr spObj1 = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj2(ptr); + spObj1 = std::move(spObj2); - TestAssert::AreEqual((void*)ptr, (void*)spObj1.Get(), L"Expected ptr"); - TestAssert::IsNull(spObj2.Get(), L"Expected null"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj1.Get(), L"Expected ptr"); + TestAssert::IsNull(spObj2.Get(), L"Expected null"); + }); } TEST_METHOD(TCntPtr_MoveAssignmentInterface) { - ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - Mso::TCntPtr spIntf = new SimpleClass(std::move(onRefCountChanged)); - spIntf = std::move(spObj); + ValidateRefCount(2, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + Mso::TCntPtr spIntf = new SimpleClass(std::move(onRefCountChanged)); + spIntf = std::move(spObj); - TestAssert::IsNull(spObj.Get(), L"Expected null"); - TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); - }); + TestAssert::IsNull(spObj.Get(), L"Expected null"); + TestAssert::AreEqual((void*)ptr, (void*)spIntf.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_MoveAssignmentSameObject) { - // Our copy assignment does not check if we use the same object. This test is to see that nothing bad happens. - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); - Mso::TCntPtr spObj(ptr); - spObj = std::move(spObj); + // Our copy assignment does not check if we use the same object. This test is to see that nothing bad happens. + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + SimpleClass* ptr = new SimpleClass(std::move(onRefCountChanged)); + Mso::TCntPtr spObj(ptr); + spObj = std::move(spObj); - TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); - }); + TestAssert::AreEqual((void*)ptr, (void*)spObj.Get(), L"Expected ptr"); + }); } TEST_METHOD(TCntPtr_NullAssignment) { - ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) - { - Mso::TCntPtr spObj = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); - spObj = nullptr; + ValidateRefCount(1, [](RefCountChangedCallback&& onRefCountChanged) { + Mso::TCntPtr spObj = new SimpleClass(RefCountChangedCallback(onRefCountChanged)); + spObj = nullptr; - TestAssert::IsNull(spObj.Get(), L"Expected null"); - }); + TestAssert::IsNull(spObj.Get(), L"Expected null"); + }); } TEST_METHOD(TCntPtr_IsEqualObject_BothISimpleClass_AreEqual) { - Mso::TCntPtr spObj = Mso::Make(); - Mso::TCntPtr spObjTwo = spObj; + Mso::TCntPtr spObj = Mso::Make(); + Mso::TCntPtr spObjTwo = spObj; - TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(spObj, spObjTwo)); + TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(spObj, spObjTwo)); } TEST_METHOD(TCntPtr_IsEqualObject_DifferentInterfaceTypes_AreEqual) { - Mso::TCntPtr spObj = Mso::Make(); - Mso::TCntPtr spSample; - TestAssert::HrSucceeded(Mso::ComUtil::HrQueryFrom(spSample, spObj)); + Mso::TCntPtr spObj = Mso::Make(); + Mso::TCntPtr spSample; + TestAssert::HrSucceeded(Mso::ComUtil::HrQueryFrom(spSample, spObj)); - TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(spObj, spSample)); + TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(spObj, spSample)); } TEST_METHOD(TCntPtr_IsEqualObject_DifferentObject_AreNotEqual) { - Mso::TCntPtr spObj = Mso::Make(); - Mso::TCntPtr spObjTwo = Mso::Make(); + Mso::TCntPtr spObj = Mso::Make(); + Mso::TCntPtr spObjTwo = Mso::Make(); - TestAssert::IsFalse(Mso::ComUtil::AreEqualObjects(spObj, spObjTwo)); + TestAssert::IsFalse(Mso::ComUtil::AreEqualObjects(spObj, spObjTwo)); } - -}; +} +; diff --git a/libs/object/tests/fixedSwarmTest.cpp b/libs/object/tests/fixedSwarmTest.cpp index 2d839b5..58a325d 100644 --- a/libs/object/tests/fixedSwarmTest.cpp +++ b/libs/object/tests/fixedSwarmTest.cpp @@ -12,337 +12,319 @@ Unit tests for classes in the ObjectSwarm.h #include #include -//#define TEST_BAD_INHERITANCE1 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this class. +//#define TEST_BAD_INHERITANCE1 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this +//class. MSO_STRUCT_GUID(IFixedSwarmSample1, "AA2EB60A-06DD-486F-AC9B-DBF1DDE21408") struct DECLSPEC_NOVTABLE IFixedSwarmSample1 : IUnknown { - virtual int GetValue1() = 0; + virtual int GetValue1() = 0; }; struct DECLSPEC_NOVTABLE IFixedSwarmSample2 : Mso::IRefCounted { - virtual int GetValue2() = 0; + virtual int GetValue2() = 0; }; struct DECLSPEC_NOVTABLE IFixedSwarmSample3 : Mso::IRefCounted { - virtual int GetValue3() = 0; + virtual int GetValue3() = 0; }; -class FixedSwarmMemberSample1 final - : public Mso::UnknownObject +class FixedSwarmMemberSample1 final : public Mso::UnknownObject { public: - FixedSwarmMemberSample1(bool& created, bool& deleted) noexcept - : m_deleted(deleted) - { - created = true; - } + FixedSwarmMemberSample1(bool& created, bool& deleted) noexcept : m_deleted(deleted) + { + created = true; + } - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~FixedSwarmMemberSample1() noexcept - { - m_deleted = true; - } + virtual ~FixedSwarmMemberSample1() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; // We can add to FixedSwarm IRefCounted objects -class FixedSwarmMemberSample2 final - : public Mso::RefCountedObject +class FixedSwarmMemberSample2 final : public Mso::RefCountedObject { public: - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } }; -class FixedSwarmMemberSample3 final - : public Mso::RefCountedObject +class FixedSwarmMemberSample3 final : public Mso::RefCountedObject { public: - virtual int GetValue3() noexcept override - { - return 3; - } + virtual int GetValue3() noexcept override + { + return 3; + } }; -class FixedSwarmMemberSampleBase - : public Mso::RefCountedObject +class FixedSwarmMemberSampleBase : public Mso::RefCountedObject { public: - FixedSwarmMemberSampleBase() noexcept - { - } + FixedSwarmMemberSampleBase() noexcept {} - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } protected: - virtual ~FixedSwarmMemberSampleBase() noexcept - { - } + virtual ~FixedSwarmMemberSampleBase() noexcept {} }; -class FixedSwarmMemberSample4Throw - : public FixedSwarmMemberSampleBase +class FixedSwarmMemberSample4Throw : public FixedSwarmMemberSampleBase { public: - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; - FixedSwarmMemberSample4Throw() - { - throw std::runtime_error("Test"); - } + FixedSwarmMemberSample4Throw() + { + throw std::runtime_error("Test"); + } }; -class FixedSwarmMemberSample5InitThrow - : public FixedSwarmMemberSampleBase +class FixedSwarmMemberSample5InitThrow : public FixedSwarmMemberSampleBase { public: - using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; - void InitializeThis() - { - UNREFERENCED_OACR(this); - throw std::runtime_error("Test"); - } + void InitializeThis() + { + UNREFERENCED_OACR(this); + throw std::runtime_error("Test"); + } }; #ifdef TEST_BAD_INHERITANCE1 class SomeVirtualClass { public: - virtual ~SomeVirtualClass() = default; + virtual ~SomeVirtualClass() = default; - int x; - int y; + int x; + int y; }; // !!! Mso::UnknownObject must be always the first one in the inheritance !!! class BadFixedSwarmMember1 final - : public SomeVirtualClass - , public Mso::UnknownObject + : public SomeVirtualClass + , public Mso::UnknownObject { public: - virtual int GetValue1() override - { - return 1; - } + virtual int GetValue1() override + { + return 1; + } }; #endif -TEST_CLASS(ObjectFixedSwarmTest) +TEST_CLASS (ObjectFixedSwarmTest) { - TEST_METHOD(ObjectFixedSwarm_NoMemberInit) - { - using Swarm1 = Mso::FixedSwarm; - Mso::TCntPtr swarm1 = Mso::Make(); - TestAssert::IsFalse(swarm1.IsEmpty()); + TEST_METHOD(ObjectFixedSwarm_NoMemberInit) + { + using Swarm1 = Mso::FixedSwarm; + Mso::TCntPtr swarm1 = Mso::Make(); + TestAssert::IsFalse(swarm1.IsEmpty()); - using Swarm2 = Mso::FixedSwarm; - Mso::TCntPtr swarm2 = Mso::Make(); - TestAssert::IsFalse(swarm2.IsEmpty()); + using Swarm2 = Mso::FixedSwarm; + Mso::TCntPtr swarm2 = Mso::Make(); + TestAssert::IsFalse(swarm2.IsEmpty()); - using Swarm3 = Mso::FixedSwarm; - Mso::TCntPtr swarm3 = Mso::Make(); - TestAssert::IsFalse(swarm3.IsEmpty()); - } + using Swarm3 = Mso::FixedSwarm; + Mso::TCntPtr swarm3 = Mso::Make(); + TestAssert::IsFalse(swarm3.IsEmpty()); + } - TEST_METHOD(ObjectFixedSwarm_NoMemberRefCount) - { - using Swarm1 = Mso::FixedSwarm; - Mso::TCntPtr swarm1 = Mso::Make(); - TestAssert::IsFalse(swarm1.IsEmpty()); - - Debug(TestAssert::AreEqual(1, swarm1->RefCount())); - Debug(TestAssert::AreEqual(1, swarm1->WeakRefCount())); + TEST_METHOD(ObjectFixedSwarm_NoMemberRefCount) + { + using Swarm1 = Mso::FixedSwarm; + Mso::TCntPtr swarm1 = Mso::Make(); + TestAssert::IsFalse(swarm1.IsEmpty()); - Mso::TCntPtr swarm11 = swarm1; - Debug(TestAssert::AreEqual(2, swarm1->RefCount())); - Debug(TestAssert::AreEqual(1, swarm1->WeakRefCount())); + Debug(TestAssert::AreEqual(1, swarm1->RefCount())); + Debug(TestAssert::AreEqual(1, swarm1->WeakRefCount())); - Mso::WeakPtr weakSwarm1 = swarm1; - Debug(TestAssert::AreEqual(2, swarm1->RefCount())); - Debug(TestAssert::AreEqual(2, swarm1->WeakRefCount())); + Mso::TCntPtr swarm11 = swarm1; + Debug(TestAssert::AreEqual(2, swarm1->RefCount())); + Debug(TestAssert::AreEqual(1, swarm1->WeakRefCount())); - Mso::WeakPtr weakSwarm11 = swarm1; - Debug(TestAssert::AreEqual(2, swarm1->RefCount())); - Debug(TestAssert::AreEqual(3, swarm1->WeakRefCount())); - } + Mso::WeakPtr weakSwarm1 = swarm1; + Debug(TestAssert::AreEqual(2, swarm1->RefCount())); + Debug(TestAssert::AreEqual(2, swarm1->WeakRefCount())); - TEST_METHOD(ObjectFixedSwarm_GetMember) - { - using Swarm3 = Mso::FixedSwarm; - Mso::TCntPtr swarm3 = Mso::Make(); - TestAssert::IsFalse(swarm3.IsEmpty()); + Mso::WeakPtr weakSwarm11 = swarm1; + Debug(TestAssert::AreEqual(2, swarm1->RefCount())); + Debug(TestAssert::AreEqual(3, swarm1->WeakRefCount())); + } - FixedSwarmMemberSample1* sample1 = swarm3->Get<0>(); - TestAssert::IsNull(sample1); + TEST_METHOD(ObjectFixedSwarm_GetMember) + { + using Swarm3 = Mso::FixedSwarm; + Mso::TCntPtr swarm3 = Mso::Make(); + TestAssert::IsFalse(swarm3.IsEmpty()); - FixedSwarmMemberSample2* sample2 = swarm3->Get<1>(); - TestAssert::IsNull(sample2); + FixedSwarmMemberSample1* sample1 = swarm3->Get<0>(); + TestAssert::IsNull(sample1); - FixedSwarmMemberSample3* sample3 = swarm3->Get<2>(); - TestAssert::IsNull(sample3); - } + FixedSwarmMemberSample2* sample2 = swarm3->Get<1>(); + TestAssert::IsNull(sample2); - TEST_METHOD(ObjectFixedSwarm_OneMember) - { - using Swarm1 = Mso::FixedSwarm; - bool created = false; - bool deleted = false; + FixedSwarmMemberSample3* sample3 = swarm3->Get<2>(); + TestAssert::IsNull(sample3); + } - { - Mso::TCntPtr swarm1 = Mso::Make(); + TEST_METHOD(ObjectFixedSwarm_OneMember) + { + using Swarm1 = Mso::FixedSwarm; + bool created = false; + bool deleted = false; - { - swarm1->MakeMember<0>(created, deleted); - Mso::TCntPtr member0 = swarm1->Get<0>(); - TestAssert::IsFalse(member0.IsEmpty()); - TestAssert::IsTrue(created); - TestAssert::IsFalse(deleted); + { + Mso::TCntPtr swarm1 = Mso::Make(); - Debug(TestAssert::AreEqual(2, swarm1->RefCount())); - Debug(TestAssert::AreEqual(2, swarm1->WeakRefCount())); - } + { + swarm1->MakeMember<0>(created, deleted); + Mso::TCntPtr member0 = swarm1->Get<0>(); + TestAssert::IsFalse(member0.IsEmpty()); + TestAssert::IsTrue(created); + TestAssert::IsFalse(deleted); - TestAssert::IsFalse(deleted); - Debug(TestAssert::AreEqual(1, swarm1->RefCount())); - Debug(TestAssert::AreEqual(2, swarm1->WeakRefCount())); - } + Debug(TestAssert::AreEqual(2, swarm1->RefCount())); + Debug(TestAssert::AreEqual(2, swarm1->WeakRefCount())); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsFalse(deleted); + Debug(TestAssert::AreEqual(1, swarm1->RefCount())); + Debug(TestAssert::AreEqual(2, swarm1->WeakRefCount())); + } - TEST_METHOD(ObjectFixedSwarm_ThreeMembers) - { - using Swarm3 = Mso::FixedSwarm; - bool created = false; - bool deleted = false; + TestAssert::IsTrue(deleted); + } - { - Mso::TCntPtr swarm3 = Mso::Make(); + TEST_METHOD(ObjectFixedSwarm_ThreeMembers) + { + using Swarm3 = Mso::FixedSwarm; + bool created = false; + bool deleted = false; - { - swarm3->MakeMember<0>(created, deleted); - Mso::TCntPtr member0 = swarm3->Get<0>(); - TestAssert::IsFalse(member0.IsEmpty()); - Debug(TestAssert::AreEqual(2, swarm3->RefCount())); - Debug(TestAssert::AreEqual(2, swarm3->WeakRefCount())); + { + Mso::TCntPtr swarm3 = Mso::Make(); - swarm3->MakeMember<1>(); - Mso::TCntPtr member1 = swarm3->Get<1>(); - TestAssert::IsFalse(member1.IsEmpty()); - Debug(TestAssert::AreEqual(3, swarm3->RefCount())); - Debug(TestAssert::AreEqual(3, swarm3->WeakRefCount())); + { + swarm3->MakeMember<0>(created, deleted); + Mso::TCntPtr member0 = swarm3->Get<0>(); + TestAssert::IsFalse(member0.IsEmpty()); + Debug(TestAssert::AreEqual(2, swarm3->RefCount())); + Debug(TestAssert::AreEqual(2, swarm3->WeakRefCount())); - swarm3->MakeMember<2>(); - Mso::TCntPtr member2 = swarm3->Get<2>(); - TestAssert::IsFalse(member2.IsEmpty()); - Debug(TestAssert::AreEqual(4, swarm3->RefCount())); - Debug(TestAssert::AreEqual(4, swarm3->WeakRefCount())); - } + swarm3->MakeMember<1>(); + Mso::TCntPtr member1 = swarm3->Get<1>(); + TestAssert::IsFalse(member1.IsEmpty()); + Debug(TestAssert::AreEqual(3, swarm3->RefCount())); + Debug(TestAssert::AreEqual(3, swarm3->WeakRefCount())); - TestAssert::IsFalse(deleted); - Debug(TestAssert::AreEqual(1, swarm3->RefCount())); - // Each object +1 for weak reference count, +1 weak reference if strong ref count != 0. - Debug(TestAssert::AreEqual(4, swarm3->WeakRefCount())); - } + swarm3->MakeMember<2>(); + Mso::TCntPtr member2 = swarm3->Get<2>(); + TestAssert::IsFalse(member2.IsEmpty()); + Debug(TestAssert::AreEqual(4, swarm3->RefCount())); + Debug(TestAssert::AreEqual(4, swarm3->WeakRefCount())); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsFalse(deleted); + Debug(TestAssert::AreEqual(1, swarm3->RefCount())); + // Each object +1 for weak reference count, +1 weak reference if strong ref count != 0. + Debug(TestAssert::AreEqual(4, swarm3->WeakRefCount())); + } - TEST_METHOD(ObjectFixedSwarm_WeakPtr) - { - using Swarm3 = Mso::FixedSwarm; - bool created = false; - bool deleted = false; + TestAssert::IsTrue(deleted); + } - Mso::WeakPtr weakMember0; - Mso::WeakPtr weakMember1; - Mso::WeakPtr weakMember2; + TEST_METHOD(ObjectFixedSwarm_WeakPtr) + { + using Swarm3 = Mso::FixedSwarm; + bool created = false; + bool deleted = false; - { - Mso::TCntPtr swarm3 = Mso::Make(); - swarm3->MakeMember<0>(created, deleted); - swarm3->MakeMember<1>(); - swarm3->MakeMember<2>(); + Mso::WeakPtr weakMember0; + Mso::WeakPtr weakMember1; + Mso::WeakPtr weakMember2; - weakMember0 = swarm3->GetWeakPtr<0>(); - weakMember1 = swarm3->GetWeakPtr<1>(); - weakMember2 = swarm3->GetWeakPtr<2>(); + { + Mso::TCntPtr swarm3 = Mso::Make(); + swarm3->MakeMember<0>(created, deleted); + swarm3->MakeMember<1>(); + swarm3->MakeMember<2>(); - TestAssert::IsFalse(weakMember0.IsExpired()); - TestAssert::IsFalse(weakMember1.IsExpired()); - TestAssert::IsFalse(weakMember2.IsExpired()); + weakMember0 = swarm3->GetWeakPtr<0>(); + weakMember1 = swarm3->GetWeakPtr<1>(); + weakMember2 = swarm3->GetWeakPtr<2>(); - TestAssert::AreEqual(1, weakMember0.GetStrongPtr()->GetValue1()); - TestAssert::AreEqual(2, weakMember1.GetStrongPtr()->GetValue2()); - TestAssert::AreEqual(3, weakMember2.GetStrongPtr()->GetValue3()); - } + TestAssert::IsFalse(weakMember0.IsExpired()); + TestAssert::IsFalse(weakMember1.IsExpired()); + TestAssert::IsFalse(weakMember2.IsExpired()); - TestAssert::IsTrue(weakMember0.IsExpired()); - TestAssert::IsTrue(weakMember1.IsExpired()); - TestAssert::IsTrue(weakMember2.IsExpired()); + TestAssert::AreEqual(1, weakMember0.GetStrongPtr()->GetValue1()); + TestAssert::AreEqual(2, weakMember1.GetStrongPtr()->GetValue2()); + TestAssert::AreEqual(3, weakMember2.GetStrongPtr()->GetValue3()); + } - TestAssert::IsNull(weakMember0.GetStrongPtr().Get()); - TestAssert::IsNull(weakMember1.GetStrongPtr().Get()); - TestAssert::IsNull(weakMember2.GetStrongPtr().Get()); - } + TestAssert::IsTrue(weakMember0.IsExpired()); + TestAssert::IsTrue(weakMember1.IsExpired()); + TestAssert::IsTrue(weakMember2.IsExpired()); - TEST_METHOD(ObjectFixedSwarm_ConstructorThrows) - { - using Swarm2 = Mso::FixedSwarm; + TestAssert::IsNull(weakMember0.GetStrongPtr().Get()); + TestAssert::IsNull(weakMember1.GetStrongPtr().Get()); + TestAssert::IsNull(weakMember2.GetStrongPtr().Get()); + } - Mso::TCntPtr swarm2 = Mso::Make(); - swarm2->MakeMember<0>(); - TestAssert::ExpectException([&]() - { - swarm2->MakeMember<1>(); - }); + TEST_METHOD(ObjectFixedSwarm_ConstructorThrows) + { + using Swarm2 = Mso::FixedSwarm; - Debug(TestAssert::AreEqual(1u, swarm2->RefCount())); - Debug(TestAssert::AreEqual(2u, swarm2->WeakRefCount())); - } + Mso::TCntPtr swarm2 = Mso::Make(); + swarm2->MakeMember<0>(); + TestAssert::ExpectException([&]() { swarm2->MakeMember<1>(); }); - TEST_METHOD(ObjectFixedSwarm_InitializeThrows) - { - using Swarm2 = Mso::FixedSwarm; + Debug(TestAssert::AreEqual(1u, swarm2->RefCount())); + Debug(TestAssert::AreEqual(2u, swarm2->WeakRefCount())); + } - Mso::TCntPtr swarm2 = Mso::Make(); - swarm2->MakeMember<0>(); - TestAssert::ExpectException([&]() - { - swarm2->MakeMember<1>(); - }); + TEST_METHOD(ObjectFixedSwarm_InitializeThrows) + { + using Swarm2 = Mso::FixedSwarm; - Debug(TestAssert::AreEqual(1u, swarm2->RefCount())); - Debug(TestAssert::AreEqual(2u, swarm2->WeakRefCount())); - } + Mso::TCntPtr swarm2 = Mso::Make(); + swarm2->MakeMember<0>(); + TestAssert::ExpectException([&]() { swarm2->MakeMember<1>(); }); + + Debug(TestAssert::AreEqual(1u, swarm2->RefCount())); + Debug(TestAssert::AreEqual(2u, swarm2->WeakRefCount())); + } #if defined(DEBUG) && defined(TEST_BAD_INHERITANCE1) - TESTMETHOD_REQUIRES_SEH(ObjectFixedSwarm_BadInheritance1) - { - using Swarm2 = Mso::FixedSwarm; - Mso::TCntPtr swarm2 = Mso::Make(); - TestAssert::ExpectVEC([&]() noexcept - { - // You will see a memory leak here because we cannot destroy object correctly. - swarm2->MakeMember<0>(); - }); - } + TESTMETHOD_REQUIRES_SEH(ObjectFixedSwarm_BadInheritance1) + { + using Swarm2 = Mso::FixedSwarm; + Mso::TCntPtr swarm2 = Mso::Make(); + TestAssert::ExpectVEC([&]() noexcept { + // You will see a memory leak here because we cannot destroy object correctly. + swarm2->MakeMember<0>(); + }); + } #endif - }; diff --git a/libs/object/tests/holderTest.cpp b/libs/object/tests/holderTest.cpp index c50fd49..e605e39 100644 --- a/libs/object/tests/holderTest.cpp +++ b/libs/object/tests/holderTest.cpp @@ -2,9 +2,9 @@ // Licensed under the MIT license. /**************************************************************************** - Holder.cpp + Holder.cpp - Unit tests for the smart pointers + Unit tests for the smart pointers ****************************************************************************/ #include "precomp.h" @@ -17,277 +17,295 @@ #include /*------------------------------------------------------------------------------ - %%Id: e308ef40-4b24-4cd2-98cb-a269c6345d81 + %%Id: e308ef40-4b24-4cd2-98cb-a269c6345d81 ------------------------------------------------------------------------------*/ class CUnknown : public IUnknown - { +{ public: - /*--------------------------------------------------------------------------- - %%Id: 8cf178db-8f93-40d9-beb1-c2cbe04feb60 - ---------------------------------------------------------------------------*/ - CUnknown() noexcept : m_cRef(0) {} - /*--------------------------------------------------------------------------- - %%Id: b3d41d41-7d5f-4190-a215-abbdf1149345 - ---------------------------------------------------------------------------*/ - virtual ~CUnknown() noexcept {} - /*--------------------------------------------------------------------------- - %%Id: eae6ae85-b193-4bdc-9e77-032456318605 - ---------------------------------------------------------------------------*/ - STDMETHOD(QueryInterface)(REFIID riid, void **ppv) noexcept override { if (riid == __uuidof(IUnknown)) { *ppv = this; AddRef(); return S_OK; } return E_NOTIMPL; } - /*--------------------------------------------------------------------------- - %%Id: 997c38a7-d5fe-456f-aaff-f3061bd07693 - ---------------------------------------------------------------------------*/ - STDMETHOD_(ULONG, AddRef)() noexcept override { return ++m_cRef; } - /*--------------------------------------------------------------------------- - %%Id: 997c38a7-d5fe-456f-aaff-f3061bd07693 - ---------------------------------------------------------------------------*/ - OACR_WARNING_SUPPRESS(NOTHROW_FUNC_THROWS, "This is test code and we want to use throwing TestAssert::IsTrue. It does not affect ship code.") - STDMETHOD_(ULONG, Release)() noexcept override { ULONG cRef = --m_cRef; TestAssert::IsTrue(static_cast(cRef) >= 0, L""); if (cRef == 0) delete this; return cRef; } - ULONG m_cRef; - }; + /*--------------------------------------------------------------------------- + %%Id: 8cf178db-8f93-40d9-beb1-c2cbe04feb60 + ---------------------------------------------------------------------------*/ + CUnknown() noexcept : m_cRef(0) {} + /*--------------------------------------------------------------------------- + %%Id: b3d41d41-7d5f-4190-a215-abbdf1149345 + ---------------------------------------------------------------------------*/ + virtual ~CUnknown() noexcept {} + /*--------------------------------------------------------------------------- + %%Id: eae6ae85-b193-4bdc-9e77-032456318605 + ---------------------------------------------------------------------------*/ + STDMETHOD(QueryInterface)(REFIID riid, void** ppv) noexcept override + { + if (riid == __uuidof(IUnknown)) + { + *ppv = this; + AddRef(); + return S_OK; + } + return E_NOTIMPL; + } + /*--------------------------------------------------------------------------- + %%Id: 997c38a7-d5fe-456f-aaff-f3061bd07693 + ---------------------------------------------------------------------------*/ + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return ++m_cRef; + } + /*--------------------------------------------------------------------------- + %%Id: 997c38a7-d5fe-456f-aaff-f3061bd07693 + ---------------------------------------------------------------------------*/ + OACR_WARNING_SUPPRESS( + NOTHROW_FUNC_THROWS, + "This is test code and we want to use throwing TestAssert::IsTrue. It does not affect ship code.") + STDMETHOD_(ULONG, Release)() noexcept override + { + ULONG cRef = --m_cRef; + TestAssert::IsTrue(static_cast(cRef) >= 0, L""); + if (cRef == 0) + delete this; + return cRef; + } + ULONG m_cRef; +}; MSO_STRUCT_GUID(ICustom, "5c58ced6-4f43-4b56-8d47-2236d00f7ccd") struct ICustom : IUnknown { - virtual void SomeMethod() = 0; + virtual void SomeMethod() = 0; }; -TEST_CLASS(HolderTests) +TEST_CLASS (HolderTests) { + /*------------------------------------------------------------------------------ + ------------------------------------------------------------------------------*/ + TEST_METHOD(Ctor) + { + Mso::THolder> pb1; + Mso::THolder> pb2(NULL); + Mso::THolder> pb3 = NULL; + Mso::THolder> pb4 = new BYTE; + } + + /*------------------------------------------------------------------------------ + ------------------------------------------------------------------------------*/ + TEST_METHOD(Assignment) + { + Mso::THolder> pb1; + Mso::THolder> pb2; + Mso::THolder> pb3 = new BYTE; + + TestAssert::IsTrue(pb1 == nullptr, L""); + TestAssert::IsTrue(pb1 == pb2, L""); + TestAssert::IsTrue(pb1 != pb3, L""); + TestAssert::IsTrue(pb3 != nullptr, L""); + + const BYTE* pbRaw = pb1; + TestAssert::IsTrue(pbRaw == nullptr, L""); + TestAssert::IsTrue(pbRaw == pb1, L""); + TestAssert::IsTrue(pbRaw != pb3, L""); + + pbRaw = pb3; + TestAssert::IsTrue(pbRaw != nullptr, L""); + TestAssert::IsTrue(pbRaw != pb1, L""); + TestAssert::IsTrue(pbRaw == pb3, L""); + } + + /*------------------------------------------------------------------------------ + ------------------------------------------------------------------------------*/ + TEST_METHOD(Swap) + { + Mso::THolder> pb1; + Mso::THolder> pb2 = new BYTE; + Mso::THolder> pb3 = new BYTE; + const BYTE* pb1Raw = pb1; + const BYTE* pb2Raw = pb2; + const BYTE* pb3Raw = pb3; + TestAssert::IsTrue(pb1Raw == nullptr, L""); + TestAssert::IsTrue(pb2Raw != nullptr, L""); + TestAssert::IsTrue(pb3Raw != nullptr, L""); + TestAssert::IsTrue(pb2Raw != pb3Raw, L""); + + pb2.Swap(pb3); + TestAssert::IsTrue(pb2Raw != pb2, L""); + TestAssert::IsTrue(pb2Raw == pb3, L""); + TestAssert::IsTrue(pb3Raw != pb3, L""); + TestAssert::IsTrue(pb3Raw == pb2, L""); + + pb3.Swap(pb2); + TestAssert::IsTrue(pb2Raw == pb2, L""); + TestAssert::IsTrue(pb2Raw != pb3, L""); + TestAssert::IsTrue(pb3Raw == pb3, L""); + TestAssert::IsTrue(pb3Raw != pb2, L""); + + pb1.Swap(pb2); + TestAssert::IsTrue(pb2Raw != pb2, L""); + TestAssert::IsTrue(pb2Raw == pb1, L""); + TestAssert::IsTrue(pb1Raw != pb1, L""); + TestAssert::IsTrue(pb1Raw == pb2, L""); + pb2.Swap(pb1); + } + + /*------------------------------------------------------------------------------ + %%Id: 4a8bb941-2f5c-488a-8bc9-9f5b8c0897be + ------------------------------------------------------------------------------*/ + TEST_METHOD(Transfer) + { + Mso::THolder> pb1; + Mso::THolder> pb2 = new BYTE; + TestAssert::IsTrue(pb1 == nullptr, L""); + TestAssert::IsTrue(pb2 != nullptr, L""); + + pb1.Transfer(pb2); + TestAssert::IsTrue(pb1 != nullptr, L""); + TestAssert::IsTrue(pb2 == nullptr, L""); + } + + /*------------------------------------------------------------------------------ + ------------------------------------------------------------------------------*/ + TEST_METHOD(Place) + { + Mso::THolder> pb1; + Mso::THolder> pb2 = new BYTE; + TestAssert::IsTrue(pb1 == nullptr, L""); + TestAssert::IsTrue(pb2 != nullptr, L""); + + pb1.Place(pb2.Detach()); + TestAssert::IsTrue(pb1 != nullptr, L""); + TestAssert::IsTrue(pb2 == nullptr, L""); + } + + /*------------------------------------------------------------------------------ + ------------------------------------------------------------------------------*/ + TEST_METHOD(Attach) + { + Mso::THolder> pb1 = new BYTE; + Mso::THolder> pb2 = new BYTE; + TestAssert::IsTrue(pb1 != nullptr, L""); + TestAssert::IsTrue(pb2 != nullptr, L""); + + pb1.Attach(pb2.Detach()); + TestAssert::IsTrue(pb1 != nullptr, L""); + TestAssert::IsTrue(pb2 == nullptr, L""); + } + + /*------------------------------------------------------------------------------ + %%Id: 040b6350-5468-48ff-b8cf-defc6ef412ad + ------------------------------------------------------------------------------*/ + TEST_METHOD(Address) + { + Mso::THolder> pb1; + Mso::THolder> pb2 = new BYTE; + TestAssert::IsTrue(pb1 == nullptr, L""); + TestAssert::IsTrue(pb2 != nullptr, L""); + + BYTE** ppb = &pb1; + TestAssert::IsTrue(ppb == pb1.Address(), L""); + TestAssert::IsTrue(ppb == pb1.GetRaw(), L""); + + *ppb = pb2.Detach(); + TestAssert::IsTrue(pb1 != nullptr, L""); + TestAssert::IsTrue(pb2 == nullptr, L""); + } + + /*------------------------------------------------------------------------------ + %%Id: afe52e28-6314-446a-bb29-d2d07ce4a845 + ------------------------------------------------------------------------------*/ + TEST_METHOD(CntPtrCore) + { + Mso::TCntPtr punk1; + Mso::TCntPtr punk2(new CUnknown()); + Mso::TCntPtr punk3(new CUnknown(), false); + punk3->AddRef(); + Mso::TCntPtr punk4(punk3); + Mso::TCntPtr punk5; + punk5 = new CUnknown(); + + TestAssert::IsTrue(punk1 == nullptr, L""); + TestAssert::IsTrue(punk2 != nullptr, L""); + TestAssert::IsTrue(punk3 != nullptr, L""); + TestAssert::IsTrue(punk4 != nullptr, L""); + TestAssert::IsTrue(punk5 != nullptr, L""); + + punk1 = punk2; + TestAssert::IsTrue(punk1->m_cRef == 2, L""); + TestAssert::IsTrue(punk2->m_cRef == 2, L""); + punk1 = punk4; + TestAssert::IsTrue(punk1->m_cRef == 3, L""); + TestAssert::IsTrue(punk2->m_cRef == 1, L""); + TestAssert::IsTrue(punk4->m_cRef == 3, L""); + punk1 = NULL; + + punk1.Swap(punk3); + punk3.Swap(punk5); + punk5.Swap(punk1); + punk3.Swap(punk5); + + punk1.Transfer(punk2); + punk2.Transfer(punk1); + punk1.Place(punk2.Detach()); + punk2.Place(punk1.Detach()); + punk1.Attach(punk2.Detach()); + punk2.Attach(punk1.Detach()); + + TestAssert::IsTrue(punk1 == nullptr, L""); + TestAssert::IsTrue(punk2 != nullptr, L""); + TestAssert::IsTrue(punk2->m_cRef == 1, L""); + TestAssert::IsTrue(punk3 != nullptr, L""); + TestAssert::IsTrue(punk3->m_cRef == 2, L""); + TestAssert::IsTrue(punk4 != nullptr, L""); + TestAssert::IsTrue(punk4->m_cRef == 2, L""); + TestAssert::IsTrue(punk3 == punk4, L""); + TestAssert::IsTrue(punk5 != nullptr, L""); + TestAssert::IsTrue(punk5->m_cRef == 1, L""); + } + + /*------------------------------------------------------------------------------ + %%Id: 5938c5b2-5d47-40a6-bd0a-903a7e126059 + ------------------------------------------------------------------------------*/ + TEST_METHOD(CntPtrMixed) + { + Mso::TCntPtr punk; + Mso::TCntPtr pistm; + TestAssert::IsTrue(pistm == nullptr, L""); + TestAssert::IsTrue(punk == nullptr, L""); + punk = pistm; + punk = &*pistm; + punk = *pistm.GetRaw(); + punk = pistm.Copy(); + *punk.Address() = pistm.Copy(); + *punk.GetRaw() = pistm.Copy(); + pistm = static_cast(static_cast(punk)); + pistm = static_cast(&*punk); + pistm = static_cast(*punk.GetRaw()); + } /*------------------------------------------------------------------------------ -------------------------------------------------------------------------------*/ -TEST_METHOD(Ctor) - { - Mso::THolder> pb1; - Mso::THolder> pb2(NULL); - Mso::THolder> pb3 = NULL; - Mso::THolder> pb4 = new BYTE; - } - -/*------------------------------------------------------------------------------ -------------------------------------------------------------------------------*/ -TEST_METHOD(Assignment) - { - Mso::THolder> pb1; - Mso::THolder> pb2; - Mso::THolder> pb3 = new BYTE; - - TestAssert::IsTrue(pb1 == nullptr, L""); - TestAssert::IsTrue(pb1 == pb2, L""); - TestAssert::IsTrue(pb1 != pb3, L""); - TestAssert::IsTrue(pb3 != nullptr, L""); - - const BYTE *pbRaw = pb1; - TestAssert::IsTrue(pbRaw == nullptr, L""); - TestAssert::IsTrue(pbRaw == pb1, L""); - TestAssert::IsTrue(pbRaw != pb3, L""); - - pbRaw = pb3; - TestAssert::IsTrue(pbRaw != nullptr, L""); - TestAssert::IsTrue(pbRaw != pb1, L""); - TestAssert::IsTrue(pbRaw == pb3, L""); - } - -/*------------------------------------------------------------------------------ -------------------------------------------------------------------------------*/ -TEST_METHOD(Swap) - { - Mso::THolder> pb1; - Mso::THolder> pb2 = new BYTE; - Mso::THolder> pb3 = new BYTE; - const BYTE *pb1Raw = pb1; - const BYTE *pb2Raw = pb2; - const BYTE *pb3Raw = pb3; - TestAssert::IsTrue(pb1Raw == nullptr, L""); - TestAssert::IsTrue(pb2Raw != nullptr, L""); - TestAssert::IsTrue(pb3Raw != nullptr, L""); - TestAssert::IsTrue(pb2Raw != pb3Raw, L""); - - pb2.Swap(pb3); - TestAssert::IsTrue(pb2Raw != pb2, L""); - TestAssert::IsTrue(pb2Raw == pb3, L""); - TestAssert::IsTrue(pb3Raw != pb3, L""); - TestAssert::IsTrue(pb3Raw == pb2, L""); - - pb3.Swap(pb2); - TestAssert::IsTrue(pb2Raw == pb2, L""); - TestAssert::IsTrue(pb2Raw != pb3, L""); - TestAssert::IsTrue(pb3Raw == pb3, L""); - TestAssert::IsTrue(pb3Raw != pb2, L""); - - pb1.Swap(pb2); - TestAssert::IsTrue(pb2Raw != pb2, L""); - TestAssert::IsTrue(pb2Raw == pb1, L""); - TestAssert::IsTrue(pb1Raw != pb1, L""); - TestAssert::IsTrue(pb1Raw == pb2, L""); - pb2.Swap(pb1); - } - -/*------------------------------------------------------------------------------ - %%Id: 4a8bb941-2f5c-488a-8bc9-9f5b8c0897be -------------------------------------------------------------------------------*/ -TEST_METHOD(Transfer) - { - Mso::THolder> pb1; - Mso::THolder> pb2 = new BYTE; - TestAssert::IsTrue(pb1 == nullptr, L""); - TestAssert::IsTrue(pb2 != nullptr, L""); - - pb1.Transfer(pb2); - TestAssert::IsTrue(pb1 != nullptr, L""); - TestAssert::IsTrue(pb2 == nullptr, L""); - } - - -/*------------------------------------------------------------------------------ -------------------------------------------------------------------------------*/ -TEST_METHOD(Place) - { - Mso::THolder> pb1; - Mso::THolder> pb2 = new BYTE; - TestAssert::IsTrue(pb1 == nullptr, L""); - TestAssert::IsTrue(pb2 != nullptr, L""); - - pb1.Place(pb2.Detach()); - TestAssert::IsTrue(pb1 != nullptr, L""); - TestAssert::IsTrue(pb2 == nullptr, L""); - } - -/*------------------------------------------------------------------------------ -------------------------------------------------------------------------------*/ -TEST_METHOD(Attach) - { - Mso::THolder> pb1 = new BYTE; - Mso::THolder> pb2 = new BYTE; - TestAssert::IsTrue(pb1 != nullptr, L""); - TestAssert::IsTrue(pb2 != nullptr, L""); - - pb1.Attach(pb2.Detach()); - TestAssert::IsTrue(pb1 != nullptr, L""); - TestAssert::IsTrue(pb2 == nullptr, L""); - } - -/*------------------------------------------------------------------------------ - %%Id: 040b6350-5468-48ff-b8cf-defc6ef412ad -------------------------------------------------------------------------------*/ -TEST_METHOD(Address) - { - Mso::THolder> pb1; - Mso::THolder> pb2 = new BYTE; - TestAssert::IsTrue(pb1 == nullptr, L""); - TestAssert::IsTrue(pb2 != nullptr, L""); - - BYTE **ppb = &pb1; - TestAssert::IsTrue(ppb == pb1.Address(), L""); - TestAssert::IsTrue(ppb == pb1.GetRaw(), L""); - - *ppb = pb2.Detach(); - TestAssert::IsTrue(pb1 != nullptr, L""); - TestAssert::IsTrue(pb2 == nullptr, L""); - } - -/*------------------------------------------------------------------------------ - %%Id: afe52e28-6314-446a-bb29-d2d07ce4a845 -------------------------------------------------------------------------------*/ -TEST_METHOD(CntPtrCore) - { - Mso::TCntPtr punk1; - Mso::TCntPtr punk2( new CUnknown() ); - Mso::TCntPtr punk3( new CUnknown(), false ); - punk3->AddRef(); - Mso::TCntPtr punk4(punk3); - Mso::TCntPtr punk5; - punk5 = new CUnknown(); - - TestAssert::IsTrue(punk1 == nullptr, L""); - TestAssert::IsTrue(punk2 != nullptr, L""); - TestAssert::IsTrue(punk3 != nullptr, L""); - TestAssert::IsTrue(punk4 != nullptr, L""); - TestAssert::IsTrue(punk5 != nullptr, L""); - - punk1 = punk2; - TestAssert::IsTrue(punk1->m_cRef == 2, L""); - TestAssert::IsTrue(punk2->m_cRef == 2, L""); - punk1 = punk4; - TestAssert::IsTrue(punk1->m_cRef == 3, L""); - TestAssert::IsTrue(punk2->m_cRef == 1, L""); - TestAssert::IsTrue(punk4->m_cRef == 3, L""); - punk1 = NULL; - - punk1.Swap(punk3); - punk3.Swap(punk5); - punk5.Swap(punk1); - punk3.Swap(punk5); - - punk1.Transfer(punk2); - punk2.Transfer(punk1); - punk1.Place(punk2.Detach()); - punk2.Place(punk1.Detach()); - punk1.Attach(punk2.Detach()); - punk2.Attach(punk1.Detach()); - - TestAssert::IsTrue(punk1 == nullptr, L""); - TestAssert::IsTrue(punk2 != nullptr, L""); - TestAssert::IsTrue(punk2->m_cRef == 1, L""); - TestAssert::IsTrue(punk3 != nullptr, L""); - TestAssert::IsTrue(punk3->m_cRef == 2, L""); - TestAssert::IsTrue(punk4 != nullptr, L""); - TestAssert::IsTrue(punk4->m_cRef == 2, L""); - TestAssert::IsTrue(punk3 == punk4, L""); - TestAssert::IsTrue(punk5 != nullptr, L""); - TestAssert::IsTrue(punk5->m_cRef == 1, L""); - } - -/*------------------------------------------------------------------------------ - %%Id: 5938c5b2-5d47-40a6-bd0a-903a7e126059 -------------------------------------------------------------------------------*/ -TEST_METHOD(CntPtrMixed) - { - Mso::TCntPtr punk; - Mso::TCntPtr pistm; - TestAssert::IsTrue(pistm == nullptr, L""); - TestAssert::IsTrue(punk == nullptr, L""); - punk = pistm; - punk = &*pistm; - punk = *pistm.GetRaw(); - punk = pistm.Copy(); - *punk.Address() = pistm.Copy(); - *punk.GetRaw() = pistm.Copy(); - pistm = static_cast(static_cast(punk)); - pistm = static_cast(&*punk); - pistm = static_cast(*punk.GetRaw()); - } - -/*------------------------------------------------------------------------------ - %%Id: b32deb10-ad98-452e-a307-8eb5d212429e + %%Id: b32deb10-ad98-452e-a307-8eb5d212429e ------------------------------------------------------------------------------*/ #ifdef MS_TARGET_WINDOWS -TEST_METHOD(CntQIPtrCore) - { - Mso::TCntPtr punk1(new CUnknown()); - Mso::TCntPtr punk2(new CUnknown()); - Mso::TCntPtr pistmQI; - - TestAssert::IsTrue(FAILED(Mso::ComUtil::HrQueryFrom(pistmQI, punk1)), L""); - TestAssert::IsTrue(SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &pistmQI)), L""); - punk1 = pistmQI; - TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(pistmQI, punk1), L""); - pistmQI.Empty(); - TestAssert::AreEqual(S_OK, Mso::ComUtil::HrQueryFrom(pistmQI, punk1)); - TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(pistmQI, punk1), L""); - } + TEST_METHOD(CntQIPtrCore) + { + Mso::TCntPtr punk1(new CUnknown()); + Mso::TCntPtr punk2(new CUnknown()); + Mso::TCntPtr pistmQI; + + TestAssert::IsTrue(FAILED(Mso::ComUtil::HrQueryFrom(pistmQI, punk1)), L""); + TestAssert::IsTrue(SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &pistmQI)), L""); + punk1 = pistmQI; + TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(pistmQI, punk1), L""); + pistmQI.Empty(); + TestAssert::AreEqual(S_OK, Mso::ComUtil::HrQueryFrom(pistmQI, punk1)); + TestAssert::IsTrue(Mso::ComUtil::AreEqualObjects(pistmQI, punk1), L""); + } #endif -TEST_METHOD(TCleanup) - // Use TCleanup to increment the variable. - { - int i = 0; - { - auto cuIncrement = Mso::TCleanup::Make([&]() noexcept { ++i; }); - TestAssert::AreEqual(0, i, L""); - } - TestAssert::AreEqual(1, i, L""); - } - + TEST_METHOD(TCleanup) + // Use TCleanup to increment the variable. + { + int i = 0; + { + auto cuIncrement = Mso::TCleanup::Make([&]() noexcept { ++i; }); + TestAssert::AreEqual(0, i, L""); + } + TestAssert::AreEqual(1, i, L""); + } }; diff --git a/libs/object/tests/lazyInitTest.cpp b/libs/object/tests/lazyInitTest.cpp index 4b94f93..daa5f20 100644 --- a/libs/object/tests/lazyInitTest.cpp +++ b/libs/object/tests/lazyInitTest.cpp @@ -11,659 +11,702 @@ #include #include - struct ICountedType : Mso::IRefCounted { - virtual int GetCallCount() const noexcept = 0; + virtual int GetCallCount() const noexcept = 0; - virtual int GetArgument0() const noexcept = 0; + virtual int GetArgument0() const noexcept = 0; - virtual char GetArgument1() const noexcept = 0; + virtual char GetArgument1() const noexcept = 0; }; class CountedType final : public Mso::RefCountedObject { - friend MakePolicy; + friend MakePolicy; public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(CountedType); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(CountedType); - int GetCallCount() const noexcept override - { - return m_callCount; - } + int GetCallCount() const noexcept override + { + return m_callCount; + } - int GetArgument0() const noexcept override - { - return m_argument0; - } + int GetArgument0() const noexcept override + { + return m_argument0; + } - char GetArgument1() const noexcept override - { - return m_argument1; - } + char GetArgument1() const noexcept override + { + return m_argument1; + } private: - explicit CountedType() noexcept - : m_callCount{ ++s_callCount } - { - } + explicit CountedType() noexcept : m_callCount{++s_callCount} {} - explicit CountedType(int argument0) noexcept - : m_callCount{ ++s_callCount }, m_argument0{ argument0 } - { - } + explicit CountedType(int argument0) noexcept : m_callCount{++s_callCount}, m_argument0{argument0} {} - explicit CountedType(int argument0, char argument1) noexcept - : m_callCount{ ++s_callCount }, m_argument0{ argument0 }, m_argument1{ argument1 } - { - } + explicit CountedType(int argument0, char argument1) noexcept + : m_callCount{++s_callCount}, m_argument0{argument0}, m_argument1{argument1} + { + } - ~CountedType() noexcept override = default; + ~CountedType() noexcept override = default; - const int m_callCount{ 0 }; + const int m_callCount{0}; - const int m_argument0{ 0 }; + const int m_argument0{0}; - const char m_argument1{ '\0' }; + const char m_argument1{'\0'}; - static std::atomic_int s_callCount; + static std::atomic_int s_callCount; }; -std::atomic_int CountedType::s_callCount{ 0 }; +std::atomic_int CountedType::s_callCount{0}; MSO_STRUCT_GUID(IUnknownType, "2F73DD3F-9255-4898-AF44-DE44158FE96E") struct IUnknownType : IUnknown { - virtual int GetArgument0() const noexcept = 0; + virtual int GetArgument0() const noexcept = 0; - virtual char GetArgument1() const noexcept = 0; + virtual char GetArgument1() const noexcept = 0; }; class UnknownType final : public Mso::UnknownObject { - friend MakePolicy; + friend MakePolicy; public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(UnknownType); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(UnknownType); - int GetArgument0() const noexcept override - { - return m_argument0; - } + int GetArgument0() const noexcept override + { + return m_argument0; + } - char GetArgument1() const noexcept override - { - return m_argument1; - } + char GetArgument1() const noexcept override + { + return m_argument1; + } private: - explicit UnknownType() noexcept = default; + explicit UnknownType() noexcept = default; - explicit UnknownType(int argument0) noexcept - : m_argument0{ argument0 } - { - } + explicit UnknownType(int argument0) noexcept : m_argument0{argument0} {} - explicit UnknownType(int argument0, char argument1) noexcept - : m_argument0{ argument0 }, m_argument1{ argument1 } - { - } + explicit UnknownType(int argument0, char argument1) noexcept : m_argument0{argument0}, m_argument1{argument1} {} - ~UnknownType() noexcept override = default; + ~UnknownType() noexcept override = default; - const int m_argument0{ 0 }; + const int m_argument0{0}; - const char m_argument1{ '\0' }; + const char m_argument1{'\0'}; }; -TEST_CLASS(LazyInitTests) +TEST_CLASS (LazyInitTests) { - TEST_METHOD(Get_CalledMultipleTimesForCountedType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get()) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForCountedType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1)) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get(1, 'A')), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForCountedType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1, 'A')) }; - TestAssert::AreEqual((void*)&(instance.Get(1)), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); - } - - TEST_METHOD(Get_AfterReleaseForCountedType_ReturnsDifferentObject) - { - Mso::Object::LazyInit instance; - - const auto callCount0{ instance.Get().GetCallCount() }; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - - const auto callCount1{ instance.Get().GetCallCount() }; - TestAssert::AreEqual( - callCount0 + 1, - callCount1, - L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); - } - - TEST_METHOD(Get_InParallelForCountedType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - std::array results; - std::array threads; - - for (size_t i{ 0 }; i < results.size(); ++i) - { - threads[i] = std::thread([&](const size_t index) noexcept -> void - { - results[index] = &(instance.Get()); - }, i); - } - - for (auto& thread : threads) - { - thread.join(); - } - - for (size_t i{ 0 }; i < results.size(); ++i) - { - TestAssert::AreEqual((void*)results[i], (void*)results[0]);// , L"Call '%zu' to Get() should return the same value as the first call.", i); - } - } - - TEST_METHOD(IsInitialized_WithUninitializedObjectForCountedType_ReturnsFalse) - { - const Mso::Object::LazyInit instance{}; - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); - } - - TEST_METHOD(IsInitialized_WithInitializedObjectForCountedType_ReturnsTru) - { - Mso::Object::LazyInit instance; - - instance.Get(); - TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); - } - - TEST_METHOD(IsInitialized_WithReleasedObjectForCountedType_ReturnsFalse) - { - Mso::Object::LazyInit instance; - - instance.Get(); - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_WithUninitializedObjectForCountedType_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_InParallelForCountedType_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - instance.Get(); - - std::array threads; - - for (size_t i{ 0 }; i < threads.size(); ++i) - { - threads[i] = std::thread([&]() noexcept -> void - { - instance.Release(); - }); - } - - for (auto& thread : threads) - { - thread.join(); - } - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - -inline static std::wstring ToString(CountedType* q) noexcept -{ - return L"CountedType"; -} - -inline static std::wstring ToString(ICountedType* q) noexcept -{ - return L"ICountedType"; -} - -inline static std::wstring ToString(UnknownType* q) noexcept -{ - return L"UnknownType"; -} - -inline static std::wstring ToString(IUnknownType* q) noexcept -{ - return L"IUnknownType"; -} - - TEST_METHOD(Get_CalledMultipleTimesForCountedTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get()) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForCountedTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1)) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get(1, 'A')), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForCountedTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1, 'A')) }; - TestAssert::AreEqual((void*)&(instance.Get(1)), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); - } - - TEST_METHOD(Get_AfterReleaseForCountedTypeWithInterface_ReturnsDifferentObject) - { - Mso::Object::LazyInit instance; - - const auto callCount0{ instance.Get().GetCallCount() }; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - - const auto callCount1{ instance.Get().GetCallCount() }; - TestAssert::AreEqual( - callCount0 + 1, - callCount1, - L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); - } - - TEST_METHOD(Get_InParallelForCountedTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - std::array results; - std::array threads; - - for (size_t i{ 0 }; i < results.size(); ++i) - { - threads[i] = std::thread([&](const size_t index) noexcept -> void - { - results[index] = &(instance.Get()); - }, i); - } - - for (auto& thread : threads) - { - thread.join(); - } - - for (size_t i{ 0 }; i < results.size(); ++i) - { - TestAssert::AreEqual((void*)results[i], (void*)results[0]);//, L"Call '%zu' to Get() should return the same value as the first call.", i); - } - } - - TEST_METHOD(IsInitialized_WithUninitializedObjectForCountedTypeWithInterface_ReturnsFalse) - { - const Mso::Object::LazyInit instance{}; - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); - } - - TEST_METHOD(IsInitialized_WithInitializedObjectForCountedTypeWithInterface_ReturnsTru) - { - Mso::Object::LazyInit instance; - - instance.Get(); - TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); - } - - TEST_METHOD(IsInitialized_WithReleasedObjectForCountedTypeWithInterface_ReturnsFalse) - { - Mso::Object::LazyInit instance; - - instance.Get(); - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_WithUninitializedObjectForCountedTypeWithInterface_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_InParallelForCountedTypeWithInterface_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - instance.Get(); - - std::array threads; - - for (size_t i{ 0 }; i < threads.size(); ++i) - { - threads[i] = std::thread([&]() noexcept -> void - { - instance.Release(); - }); - } - - for (auto& thread : threads) - { - thread.join(); - } - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Get_CalledMultipleTimesForUnknownType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get()) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForUnknownType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1)) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get(1, 'A')), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForUnknownType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1, 'A')) }; - TestAssert::AreEqual((void*)&(instance.Get(1)), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); - } - - TEST_METHOD(Get_AfterReleaseForUnknownType_ReturnsDifferentObject) - { - Mso::Object::LazyInit instance; - - const auto callCount0{ instance.Get().GetCallCount() }; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - - const auto callCount1{ instance.Get().GetCallCount() }; - TestAssert::AreEqual( - callCount0 + 1, - callCount1, - L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); - } - - TEST_METHOD(Get_InParallelForUnknownType_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - std::array results; - std::array threads; - - for (size_t i{ 0 }; i < results.size(); ++i) - { - threads[i] = std::thread([&](const size_t index) noexcept -> void - { - results[index] = &(instance.Get()); - }, i); - } - - for (auto& thread : threads) - { - thread.join(); - } - - for (size_t i{ 0 }; i < results.size(); ++i) - { - TestAssert::AreEqual((void*)results[i], (void*)results[0]);// , L"Call '%zu' to Get() should return the same value as the first call.", i); - } - } - - TEST_METHOD(IsInitialized_WithUninitializedObjectForUnknownType_ReturnsFalse) - { - const Mso::Object::LazyInit instance{}; - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); - } - - TEST_METHOD(IsInitialized_WithInitializedObjectForUnknownType_ReturnsTru) - { - Mso::Object::LazyInit instance; - - instance.Get(); - TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); - } - - TEST_METHOD(IsInitialized_WithReleasedObjectForUnknownType_ReturnsFalse) - { - Mso::Object::LazyInit instance; - - instance.Get(); - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_WithUninitializedObjectForUnknownType_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_InParallelForUnknownType_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - instance.Get(); - - std::array threads; - - for (size_t i{ 0 }; i < threads.size(); ++i) - { - threads[i] = std::thread([&]() noexcept -> void - { - instance.Release(); - }); - } - - for (auto& thread : threads) - { - thread.join(); - } - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Get_CalledMultipleTimesForUnknownTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get()) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForUnknownTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1)) }; - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get(1, 'A')), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); - } - - TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForUnknownTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - - const auto pointer{ &(instance.Get(1, 'A')) }; - TestAssert::AreEqual((void*)&(instance.Get(1)), (void*)pointer, L"Instance should always be the same when calling Get() the second time."); - TestAssert::AreEqual((void*)&(instance.Get()), (void*)pointer, L"Instance should always be the same when calling Get() the third time."); - - TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); - TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); - } - - TEST_METHOD(Get_AfterReleaseForUnknownTypeWithInterface_ReturnsDifferentObject) - { - Mso::Object::LazyInit instance; - - const auto callCount0{ instance.Get().GetCallCount() }; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - - const auto callCount1{ instance.Get().GetCallCount() }; - TestAssert::AreEqual( - callCount0 + 1, - callCount1, - L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); - } - - TEST_METHOD(Get_InParallelForUnknownTypeWithInterface_ReturnsSameObject) - { - Mso::Object::LazyInit instance; - std::array results; - std::array threads; - - for (size_t i{ 0 }; i < results.size(); ++i) - { - threads[i] = std::thread([&](const size_t index) noexcept -> void - { - results[index] = &(instance.Get()); - }, i); - } - - for (auto& thread : threads) - { - thread.join(); - } - - for (size_t i{ 0 }; i < results.size(); ++i) - { - TestAssert::AreEqual((void*)results[i], (void*)results[0]);// , L"Call '%zu' to Get() should return the same value as the first call.", i); - } - } - - TEST_METHOD(IsInitialized_WithUninitializedObjectForUnknownTypeWithInterface_ReturnsFalse) - { - const Mso::Object::LazyInit instance{}; - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); - } - - TEST_METHOD(IsInitialized_WithInitializedObjectForUnknownTypeWithInterface_ReturnsTru) - { - Mso::Object::LazyInit instance; - - instance.Get(); - TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); - } - - TEST_METHOD(IsInitialized_WithReleasedObjectForUnknownTypeWithInterface_ReturnsFalse) - { - Mso::Object::LazyInit instance; - - instance.Get(); - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_WithUninitializedObjectForUnknownTypeWithInterface_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - - instance.Release(); - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } - - TEST_METHOD(Release_InParallelForUnknownTypeWithInterface_SilentlySucceeds) - { - Mso::Object::LazyInit instance; - instance.Get(); - - std::array threads; - - for (size_t i{ 0 }; i < threads.size(); ++i) - { - threads[i] = std::thread([&]() noexcept -> void - { - instance.Release(); - }); - } - - for (auto& thread : threads) - { - thread.join(); - } - - TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); - } + TEST_METHOD(Get_CalledMultipleTimesForCountedType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get())}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForCountedType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1))}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get(1, 'A')), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForCountedType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1, 'A'))}; + TestAssert::AreEqual( + (void*)&(instance.Get(1)), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); + } + + TEST_METHOD(Get_AfterReleaseForCountedType_ReturnsDifferentObject) + { + Mso::Object::LazyInit instance; + + const auto callCount0{instance.Get().GetCallCount()}; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + + const auto callCount1{instance.Get().GetCallCount()}; + TestAssert::AreEqual( + callCount0 + 1, + callCount1, + L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); + } + + TEST_METHOD(Get_InParallelForCountedType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + std::array results; + std::array threads; + + for (size_t i{0}; i < results.size(); ++i) + { + threads[i] = std::thread([&](const size_t index) noexcept -> void { results[index] = &(instance.Get()); }, i); + } + + for (auto& thread : threads) + { + thread.join(); + } + + for (size_t i{0}; i < results.size(); ++i) + { + TestAssert::AreEqual( + (void*)results[i], + (void*)results[0]); // , L"Call '%zu' to Get() should return the same value as the first call.", i); + } + } + + TEST_METHOD(IsInitialized_WithUninitializedObjectForCountedType_ReturnsFalse) + { + const Mso::Object::LazyInit instance{}; + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); + } + + TEST_METHOD(IsInitialized_WithInitializedObjectForCountedType_ReturnsTru) + { + Mso::Object::LazyInit instance; + + instance.Get(); + TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); + } + + TEST_METHOD(IsInitialized_WithReleasedObjectForCountedType_ReturnsFalse) + { + Mso::Object::LazyInit instance; + + instance.Get(); + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_WithUninitializedObjectForCountedType_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_InParallelForCountedType_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + instance.Get(); + + std::array threads; + + for (size_t i{0}; i < threads.size(); ++i) + { + threads[i] = std::thread([&]() noexcept -> void { instance.Release(); }); + } + + for (auto& thread : threads) + { + thread.join(); + } + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + inline static std::wstring ToString(CountedType * q) noexcept + { + return L"CountedType"; + } + + inline static std::wstring ToString(ICountedType * q) noexcept + { + return L"ICountedType"; + } + + inline static std::wstring ToString(UnknownType * q) noexcept + { + return L"UnknownType"; + } + + inline static std::wstring ToString(IUnknownType * q) noexcept + { + return L"IUnknownType"; + } + + TEST_METHOD(Get_CalledMultipleTimesForCountedTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get())}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForCountedTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1))}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get(1, 'A')), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForCountedTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1, 'A'))}; + TestAssert::AreEqual( + (void*)&(instance.Get(1)), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); + } + + TEST_METHOD(Get_AfterReleaseForCountedTypeWithInterface_ReturnsDifferentObject) + { + Mso::Object::LazyInit instance; + + const auto callCount0{instance.Get().GetCallCount()}; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + + const auto callCount1{instance.Get().GetCallCount()}; + TestAssert::AreEqual( + callCount0 + 1, + callCount1, + L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); + } + + TEST_METHOD(Get_InParallelForCountedTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + std::array results; + std::array threads; + + for (size_t i{0}; i < results.size(); ++i) + { + threads[i] = std::thread([&](const size_t index) noexcept -> void { results[index] = &(instance.Get()); }, i); + } + + for (auto& thread : threads) + { + thread.join(); + } + + for (size_t i{0}; i < results.size(); ++i) + { + TestAssert::AreEqual( + (void*)results[i], + (void*)results[0]); //, L"Call '%zu' to Get() should return the same value as the first call.", i); + } + } + + TEST_METHOD(IsInitialized_WithUninitializedObjectForCountedTypeWithInterface_ReturnsFalse) + { + const Mso::Object::LazyInit instance{}; + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); + } + + TEST_METHOD(IsInitialized_WithInitializedObjectForCountedTypeWithInterface_ReturnsTru) + { + Mso::Object::LazyInit instance; + + instance.Get(); + TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); + } + + TEST_METHOD(IsInitialized_WithReleasedObjectForCountedTypeWithInterface_ReturnsFalse) + { + Mso::Object::LazyInit instance; + + instance.Get(); + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_WithUninitializedObjectForCountedTypeWithInterface_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_InParallelForCountedTypeWithInterface_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + instance.Get(); + + std::array threads; + + for (size_t i{0}; i < threads.size(); ++i) + { + threads[i] = std::thread([&]() noexcept -> void { instance.Release(); }); + } + + for (auto& thread : threads) + { + thread.join(); + } + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Get_CalledMultipleTimesForUnknownType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get())}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForUnknownType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1))}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get(1, 'A')), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForUnknownType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1, 'A'))}; + TestAssert::AreEqual( + (void*)&(instance.Get(1)), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); + } + + TEST_METHOD(Get_AfterReleaseForUnknownType_ReturnsDifferentObject) + { + Mso::Object::LazyInit instance; + + const auto callCount0{instance.Get().GetCallCount()}; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + + const auto callCount1{instance.Get().GetCallCount()}; + TestAssert::AreEqual( + callCount0 + 1, + callCount1, + L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); + } + + TEST_METHOD(Get_InParallelForUnknownType_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + std::array results; + std::array threads; + + for (size_t i{0}; i < results.size(); ++i) + { + threads[i] = std::thread([&](const size_t index) noexcept -> void { results[index] = &(instance.Get()); }, i); + } + + for (auto& thread : threads) + { + thread.join(); + } + + for (size_t i{0}; i < results.size(); ++i) + { + TestAssert::AreEqual( + (void*)results[i], + (void*)results[0]); // , L"Call '%zu' to Get() should return the same value as the first call.", i); + } + } + + TEST_METHOD(IsInitialized_WithUninitializedObjectForUnknownType_ReturnsFalse) + { + const Mso::Object::LazyInit instance{}; + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); + } + + TEST_METHOD(IsInitialized_WithInitializedObjectForUnknownType_ReturnsTru) + { + Mso::Object::LazyInit instance; + + instance.Get(); + TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); + } + + TEST_METHOD(IsInitialized_WithReleasedObjectForUnknownType_ReturnsFalse) + { + Mso::Object::LazyInit instance; + + instance.Get(); + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_WithUninitializedObjectForUnknownType_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_InParallelForUnknownType_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + instance.Get(); + + std::array threads; + + for (size_t i{0}; i < threads.size(); ++i) + { + threads[i] = std::thread([&]() noexcept -> void { instance.Release(); }); + } + + for (auto& thread : threads) + { + thread.join(); + } + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Get_CalledMultipleTimesForUnknownTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get())}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 0, L"Argument 0 should have the default value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith1Parameter_CalledMultipleTimesForUnknownTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1))}; + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get(1, 'A')), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), '\0', L"Argument 1 should have the default value."); + } + + TEST_METHOD(GetWith2Parameters_CalledMultipleTimesForUnknownTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + + const auto pointer{&(instance.Get(1, 'A'))}; + TestAssert::AreEqual( + (void*)&(instance.Get(1)), + (void*)pointer, + L"Instance should always be the same when calling Get() the second time."); + TestAssert::AreEqual( + (void*)&(instance.Get()), + (void*)pointer, + L"Instance should always be the same when calling Get() the third time."); + + TestAssert::AreEqual(pointer->GetArgument0(), 1, L"Argument 0 should have the specified value."); + TestAssert::AreEqual(pointer->GetArgument1(), 'A', L"Argument 1 should have the specified value."); + } + + TEST_METHOD(Get_AfterReleaseForUnknownTypeWithInterface_ReturnsDifferentObject) + { + Mso::Object::LazyInit instance; + + const auto callCount0{instance.Get().GetCallCount()}; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + + const auto callCount1{instance.Get().GetCallCount()}; + TestAssert::AreEqual( + callCount0 + 1, + callCount1, + L"The call count from before calling Release() should be one less than the one after, thereby ensuring the expected number of objects were created."); + } + + TEST_METHOD(Get_InParallelForUnknownTypeWithInterface_ReturnsSameObject) + { + Mso::Object::LazyInit instance; + std::array results; + std::array threads; + + for (size_t i{0}; i < results.size(); ++i) + { + threads[i] = std::thread([&](const size_t index) noexcept -> void { results[index] = &(instance.Get()); }, i); + } + + for (auto& thread : threads) + { + thread.join(); + } + + for (size_t i{0}; i < results.size(); ++i) + { + TestAssert::AreEqual( + (void*)results[i], + (void*)results[0]); // , L"Call '%zu' to Get() should return the same value as the first call.", i); + } + } + + TEST_METHOD(IsInitialized_WithUninitializedObjectForUnknownTypeWithInterface_ReturnsFalse) + { + const Mso::Object::LazyInit instance{}; + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized."); + } + + TEST_METHOD(IsInitialized_WithInitializedObjectForUnknownTypeWithInterface_ReturnsTru) + { + Mso::Object::LazyInit instance; + + instance.Get(); + TestAssert::IsTrue(instance.IsInitialized(), L"Instance should be initialized."); + } + + TEST_METHOD(IsInitialized_WithReleasedObjectForUnknownTypeWithInterface_ReturnsFalse) + { + Mso::Object::LazyInit instance; + + instance.Get(); + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_WithUninitializedObjectForUnknownTypeWithInterface_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + + instance.Release(); + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } + + TEST_METHOD(Release_InParallelForUnknownTypeWithInterface_SilentlySucceeds) + { + Mso::Object::LazyInit instance; + instance.Get(); + + std::array threads; + + for (size_t i{0}; i < threads.size(); ++i) + { + threads[i] = std::thread([&]() noexcept -> void { instance.Release(); }); + } + + for (auto& thread : threads) + { + thread.join(); + } + + TestAssert::IsFalse(instance.IsInitialized(), L"Instance should not be initialized after Release()."); + } }; \ No newline at end of file diff --git a/libs/object/tests/objectRefCountTest.cpp b/libs/object/tests/objectRefCountTest.cpp index 09582ef..2d3b153 100644 --- a/libs/object/tests/objectRefCountTest.cpp +++ b/libs/object/tests/objectRefCountTest.cpp @@ -12,127 +12,114 @@ Unit tests for classes in the ObjectRefCount.h #include "testAllocators.h" #include -class ObjectRefCountSample1 final - : public Mso::RefCountedObjectNoVTable +class ObjectRefCountSample1 final : public Mso::RefCountedObjectNoVTable { public: - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - ObjectRefCountSample1(int value, bool& deleted) noexcept - : m_value(value) - , m_deleted(deleted) - { - } + ObjectRefCountSample1(int value, bool& deleted) noexcept : m_value(value), m_deleted(deleted) {} - ~ObjectRefCountSample1() noexcept - { - m_deleted = true; - } + ~ObjectRefCountSample1() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool& m_deleted; + int m_value; + bool& m_deleted; }; - -class ObjectRefCountSample2Init final - : public Mso::RefCountedObjectNoVTable +class ObjectRefCountSample2Init final : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - void InitializeThis(int value, bool& deleted) noexcept - { - m_value = value; - m_deleted = &deleted; - } + void InitializeThis(int value, bool& deleted) noexcept + { + m_value = value; + m_deleted = &deleted; + } - ObjectRefCountSample2Init() noexcept = default; + ObjectRefCountSample2Init() noexcept = default; - ~ObjectRefCountSample2Init() noexcept - { - *m_deleted = true; - } + ~ObjectRefCountSample2Init() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool* m_deleted; + int m_value; + bool* m_deleted; }; - class ObjectRefCountSample3CannotAllocate final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { }; - -class ObjectRefCountSample4Throw final - : public Mso::RefCountedObjectNoVTable +class ObjectRefCountSample4Throw final : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; private: - ObjectRefCountSample4Throw(bool& deleted) - : m_deleted(deleted) - { - throw std::runtime_error("Test"); - } + ObjectRefCountSample4Throw(bool& deleted) : m_deleted(deleted) + { + throw std::runtime_error("Test"); + } - ~ObjectRefCountSample4Throw() noexcept - { - m_deleted = true; - } + ~ObjectRefCountSample4Throw() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - bool& m_deleted; + bool& m_deleted; }; - -class ObjectRefCountSample5InitThrow final - : public Mso::RefCountedObjectNoVTable +class ObjectRefCountSample5InitThrow final : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; private: - void InitializeThis(bool& deleted) - { - m_deleted = &deleted; - throw std::runtime_error("Test"); - } + void InitializeThis(bool& deleted) + { + m_deleted = &deleted; + throw std::runtime_error("Test"); + } - ObjectRefCountSample5InitThrow() noexcept = default; + ObjectRefCountSample5InitThrow() noexcept = default; - ~ObjectRefCountSample5InitThrow() noexcept - { - *m_deleted = true; - } + ~ObjectRefCountSample5InitThrow() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - bool* m_deleted { nullptr }; + bool* m_deleted{nullptr}; }; //============================================================================= @@ -140,397 +127,372 @@ private: //============================================================================= class ObjectRefCountSample11 final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - ObjectRefCountSample11(int value, bool& deleted) noexcept - : m_value(value) - , m_deleted(deleted) - { - } + ObjectRefCountSample11(int value, bool& deleted) noexcept : m_value(value), m_deleted(deleted) {} - ~ObjectRefCountSample11() noexcept - { - m_deleted = true; - } + ~ObjectRefCountSample11() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool& m_deleted; + int m_value; + bool& m_deleted; }; - class ObjectRefCountSample21Init final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - void InitializeThis(int value, bool& deleted) noexcept - { - m_value = value; - m_deleted = &deleted; - } + void InitializeThis(int value, bool& deleted) noexcept + { + m_value = value; + m_deleted = &deleted; + } - ObjectRefCountSample21Init() noexcept = default; + ObjectRefCountSample21Init() noexcept = default; - ~ObjectRefCountSample21Init() noexcept - { - *m_deleted = true; - } + ~ObjectRefCountSample21Init() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool* m_deleted; + int m_value; + bool* m_deleted; }; - class ObjectRefCountSample31CannotAllocate final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { }; - class ObjectRefCountSample41Throw final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; private: - ObjectRefCountSample41Throw(bool& deleted) - : m_deleted(deleted) - { - throw std::runtime_error("Test"); - } + ObjectRefCountSample41Throw(bool& deleted) : m_deleted(deleted) + { + throw std::runtime_error("Test"); + } - ~ObjectRefCountSample41Throw() noexcept - { - m_deleted = true; - } + ~ObjectRefCountSample41Throw() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - bool& m_deleted; + bool& m_deleted; }; - class ObjectRefCountSample51InitThrow final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; private: - void InitializeThis(bool& deleted) - { - m_deleted = &deleted; - throw std::runtime_error("Test"); - } + void InitializeThis(bool& deleted) + { + m_deleted = &deleted; + throw std::runtime_error("Test"); + } - ObjectRefCountSample51InitThrow() noexcept = default; + ObjectRefCountSample51InitThrow() noexcept = default; - ~ObjectRefCountSample51InitThrow() noexcept - { - *m_deleted = true; - } + ~ObjectRefCountSample51InitThrow() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - bool* m_deleted { nullptr }; + bool* m_deleted{nullptr}; }; -TEST_CLASS(ObjectRefCountTest) +TEST_CLASS (ObjectRefCountTest) { - TEST_METHOD(ObjectRefCount_Make) - { - TestAssert::AreEqual(sizeof(uint32_t), sizeof(Mso::RefCountedObjectNoVTable)); + TEST_METHOD(ObjectRefCount_Make) + { + TestAssert::AreEqual(sizeof(uint32_t), sizeof(Mso::RefCountedObjectNoVTable)); - bool deleted = false; - { - Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/deleted); - { - Debug(TestAssert::AreEqual(1u, obj1->RefCount())); - TestAssert::AreEqual(5, obj1->Value()); + bool deleted = false; + { + Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/ deleted); + { + Debug(TestAssert::AreEqual(1u, obj1->RefCount())); + TestAssert::AreEqual(5, obj1->Value()); - Mso::TCntPtr obj2(obj1); - Debug(TestAssert::AreEqual(2u, obj1->RefCount())); - TestAssert::IsNotNull(obj2.Get()); - TestAssert::IsTrue(obj1.Get() == obj2.Get()); - } - Debug(TestAssert::AreEqual(1u, obj1->RefCount())); - } + Mso::TCntPtr obj2(obj1); + Debug(TestAssert::AreEqual(2u, obj1->RefCount())); + TestAssert::IsNotNull(obj2.Get()); + TestAssert::IsTrue(obj1.Get() == obj2.Get()); + } + Debug(TestAssert::AreEqual(1u, obj1->RefCount())); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectRefCount_Make_InitializeThis) - { - bool deleted = false; - { - auto obj = Mso::Make(5, /*ref*/deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_Make_InitializeThis) + { + bool deleted = false; + { + auto obj = Mso::Make(5, /*ref*/ deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectRefCount_Make_CannotAllocate) - { - Mso::TCntPtr obj; - TestAssert::ExpectVEC([&]() noexcept - { - obj = Mso::Make(); - }); + TEST_METHOD(ObjectRefCount_Make_CannotAllocate) + { + Mso::TCntPtr obj; + TestAssert::ExpectVEC([&]() noexcept { obj = Mso::Make(); }); - TestAssert::IsTrue(obj.IsEmpty()); - } + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_Make_CtorThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::Make(/*ref*/deleted); - }); + TEST_METHOD(ObjectRefCount_Make_CtorThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::Make(/*ref*/ deleted); }); - TestAssert::IsFalse(deleted); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } + TestAssert::IsFalse(deleted); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_Make_InitializeThisThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::Make(/*ref*/deleted); - }); + TEST_METHOD(ObjectRefCount_Make_InitializeThisThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::Make(/*ref*/ deleted); }); - TestAssert::IsTrue(deleted); // If InitializeThis throws then destructor must be called. - TestAssert::IsTrue(obj.IsEmpty()); - } + TestAssert::IsTrue(deleted); // If InitializeThis throws then destructor must be called. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_MakeElseNull) - { - bool deleted = false; - { - auto obj = Mso::MakeElseNull(5, /*ref*/deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_MakeElseNull) + { + bool deleted = false; + { + auto obj = Mso::MakeElseNull(5, /*ref*/ deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectRefCount_MakeElseNull_InitializeThis) - { - bool deleted = false; - { - auto obj = Mso::MakeElseNull(5, /*ref*/deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_MakeElseNull_InitializeThis) + { + bool deleted = false; + { + auto obj = Mso::MakeElseNull(5, /*ref*/ deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectRefCount_MakeElseNull_CannotAllocate) - { - auto obj = Mso::MakeElseNull(); - TestAssert::IsNull(obj.Get()); - } + TEST_METHOD(ObjectRefCount_MakeElseNull_CannotAllocate) + { + auto obj = Mso::MakeElseNull(); + TestAssert::IsNull(obj.Get()); + } - TEST_METHOD(ObjectRefCount_MakeElseNull_CtorThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::MakeElseNull(/*ref*/deleted); - }); + TEST_METHOD(ObjectRefCount_MakeElseNull_CtorThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::MakeElseNull(/*ref*/ deleted); }); - TestAssert::IsFalse(deleted); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } + TestAssert::IsFalse(deleted); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_MakeElseNull_InitializeThisThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::MakeElseNull(/*ref*/deleted); - }); + TEST_METHOD(ObjectRefCount_MakeElseNull_InitializeThisThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::MakeElseNull(/*ref*/ deleted); }); - TestAssert::IsTrue(deleted); // If InitializeThis throws then we must call destructor. - TestAssert::IsTrue(obj.IsEmpty()); - } + TestAssert::IsTrue(deleted); // If InitializeThis throws then we must call destructor. + TestAssert::IsTrue(obj.IsEmpty()); + } - struct AllocTestState - { - bool AllocCalled; - bool FreeCalled; - bool Deleted; - }; + struct AllocTestState + { + bool AllocCalled; + bool FreeCalled; + bool Deleted; + }; - static void AssertAllocState(const AllocTestState& state, bool deleted = true) noexcept - { - TestAssert::IsTrue(state.AllocCalled, L"Allocate expected to be called"); - TestAssert::IsTrue(state.FreeCalled, L"Deallocate expected to be called"); - TestAssert::AreEqual(deleted, state.Deleted, L"Destructor to be called"); - } + static void AssertAllocState(const AllocTestState& state, bool deleted = true) noexcept + { + TestAssert::IsTrue(state.AllocCalled, L"Allocate expected to be called"); + TestAssert::IsTrue(state.FreeCalled, L"Deallocate expected to be called"); + TestAssert::AreEqual(deleted, state.Deleted, L"Destructor to be called"); + } - TEST_METHOD(ObjectRefCount_MakeAlloc) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_MakeAlloc) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectRefCount_MakeAlloc_InitializeThis) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_MakeAlloc_InitializeThis) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectRefCount_MakeAlloc_CannotAllocate) - { - Mso::TCntPtr obj; - TestAssert::ExpectVEC([&]() noexcept - { - AllocTestState state = {}; - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAlloc(&memHeap); - }); + TEST_METHOD(ObjectRefCount_MakeAlloc_CannotAllocate) + { + Mso::TCntPtr obj; + TestAssert::ExpectVEC([&]() noexcept { + AllocTestState state = {}; + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAlloc(&memHeap); + }); - TestAssert::IsTrue(obj.IsEmpty()); - } + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_MakeAlloc_CtorThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAlloc(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectRefCount_MakeAlloc_CtorThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAlloc(&memHeap, /*ref*/ state.Deleted); + }); - AssertAllocState(state, /*deleted:*/false); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state, /*deleted:*/ false); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_MakeAlloc_InitializeThisThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAlloc(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectRefCount_MakeAlloc_InitializeThisThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAlloc(&memHeap, /*ref*/ state.Deleted); + }); - AssertAllocState(state); // If InitializeThis throws then destructor must be called. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state); // If InitializeThis throws then destructor must be called. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_MakeAllocElseNull) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_MakeAllocElseNull) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectRefCount_MakeAllocElseNull_InitializeThis) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectRefCount_MakeAllocElseNull_InitializeThis) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectRefCount_MakeAllocElseNull_CannotAllocate) - { - AllocTestState state = {}; - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAllocElseNull(&memHeap); - TestAssert::IsNull(obj.Get()); - } + TEST_METHOD(ObjectRefCount_MakeAllocElseNull_CannotAllocate) + { + AllocTestState state = {}; + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAllocElseNull(&memHeap); + TestAssert::IsNull(obj.Get()); + } - TEST_METHOD(ObjectRefCount_MakeAllocElseNull_CtorThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectRefCount_MakeAllocElseNull_CtorThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/ state.Deleted); + }); - AssertAllocState(state, /*deleted:*/false); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state, /*deleted:*/ false); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectRefCount_MakeAllocElseNull_InitializeThisThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectRefCount_MakeAllocElseNull_InitializeThisThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/ state.Deleted); + }); - AssertAllocState(state); // If InitializeThis throws then we must call destructor. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state); // If InitializeThis throws then we must call destructor. + TestAssert::IsTrue(obj.IsEmpty()); + } }; diff --git a/libs/object/tests/objectWithWeakRefTest.cpp b/libs/object/tests/objectWithWeakRefTest.cpp index c5e4419..ed183d9 100644 --- a/libs/object/tests/objectWithWeakRefTest.cpp +++ b/libs/object/tests/objectWithWeakRefTest.cpp @@ -12,570 +12,534 @@ Unit tests for classes in the ObjectRefCount.h #include class ObjectWithWeakRefSample1 final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - ObjectWithWeakRefSample1(int value, bool& deleted) noexcept - : m_value(value) - , m_deleted(deleted) - { - } + ObjectWithWeakRefSample1(int value, bool& deleted) noexcept : m_value(value), m_deleted(deleted) {} - ~ObjectWithWeakRefSample1() noexcept - { - m_deleted = true; - } + ~ObjectWithWeakRefSample1() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool& m_deleted; + int m_value; + bool& m_deleted; }; class ObjectWithWeakRefSample2Init final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - void InitializeThis(int value, bool& deleted) noexcept - { - m_value = value; - m_deleted = &deleted; - } + void InitializeThis(int value, bool& deleted) noexcept + { + m_value = value; + m_deleted = &deleted; + } - ObjectWithWeakRefSample2Init() noexcept = default; + ObjectWithWeakRefSample2Init() noexcept = default; - ~ObjectWithWeakRefSample2Init() noexcept - { - *m_deleted = true; - } + ~ObjectWithWeakRefSample2Init() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool* m_deleted; + int m_value; + bool* m_deleted; }; - class ObjectWithWeakRefSample3CannotAllocate final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { }; - class ObjectWithWeakRefSample4Throw final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; private: - ObjectWithWeakRefSample4Throw(bool& deleted) - : m_deleted(deleted) - { - throw std::runtime_error("Test"); - } + ObjectWithWeakRefSample4Throw(bool& deleted) : m_deleted(deleted) + { + throw std::runtime_error("Test"); + } - ~ObjectWithWeakRefSample4Throw() noexcept - { - m_deleted = true; - } + ~ObjectWithWeakRefSample4Throw() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - bool& m_deleted; + bool& m_deleted; }; - class ObjectWithWeakRefSample5InitThrow final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; private: - void InitializeThis(bool& deleted) - { - m_deleted = &deleted; - throw std::runtime_error("Test"); - } + void InitializeThis(bool& deleted) + { + m_deleted = &deleted; + throw std::runtime_error("Test"); + } - ObjectWithWeakRefSample5InitThrow() noexcept = default; + ObjectWithWeakRefSample5InitThrow() noexcept = default; - ~ObjectWithWeakRefSample5InitThrow() noexcept - { - *m_deleted = true; - } + ~ObjectWithWeakRefSample5InitThrow() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - bool* m_deleted { nullptr }; + bool* m_deleted{nullptr}; }; - //============================================================================= // Classes below use stateful allocator //============================================================================= class ObjectWithWeakRefSample11 final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - ObjectWithWeakRefSample11(int value, bool& deleted) noexcept - : m_value(value) - , m_deleted(deleted) - { - } + ObjectWithWeakRefSample11(int value, bool& deleted) noexcept : m_value(value), m_deleted(deleted) {} - ~ObjectWithWeakRefSample11() noexcept - { - m_deleted = true; - } + ~ObjectWithWeakRefSample11() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool& m_deleted; + int m_value; + bool& m_deleted; }; class ObjectWithWeakRefSample21Init final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - int Value() const noexcept - { - return m_value; - } + int Value() const noexcept + { + return m_value; + } private: - void InitializeThis(int value, bool& deleted) noexcept - { - m_value = value; - m_deleted = &deleted; - } + void InitializeThis(int value, bool& deleted) noexcept + { + m_value = value; + m_deleted = &deleted; + } - ObjectWithWeakRefSample21Init() noexcept = default; + ObjectWithWeakRefSample21Init() noexcept = default; - ~ObjectWithWeakRefSample21Init() noexcept - { - *m_deleted = true; - } + ~ObjectWithWeakRefSample21Init() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - int m_value; - bool* m_deleted; + int m_value; + bool* m_deleted; }; - class ObjectWithWeakRefSample31CannotAllocate final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { }; - class ObjectWithWeakRefSample41Throw final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; private: - ObjectWithWeakRefSample41Throw(bool& deleted) - : m_deleted(deleted) - { - throw std::runtime_error("Test"); - } + ObjectWithWeakRefSample41Throw(bool& deleted) : m_deleted(deleted) + { + throw std::runtime_error("Test"); + } - ~ObjectWithWeakRefSample41Throw() noexcept - { - m_deleted = true; - } + ~ObjectWithWeakRefSample41Throw() noexcept + { + m_deleted = true; + } - friend MakePolicy; // To support private constructor - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor + friend RefCountPolicy; // To support private destructor private: - bool& m_deleted; + bool& m_deleted; }; - class ObjectWithWeakRefSample51InitThrow final - : public Mso::RefCountedObjectNoVTable + : public Mso::RefCountedObjectNoVTable { public: - using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; private: - void InitializeThis(bool& deleted) - { - m_deleted = &deleted; - throw std::runtime_error("Test"); - } + void InitializeThis(bool& deleted) + { + m_deleted = &deleted; + throw std::runtime_error("Test"); + } - ObjectWithWeakRefSample51InitThrow() noexcept = default; + ObjectWithWeakRefSample51InitThrow() noexcept = default; - ~ObjectWithWeakRefSample51InitThrow() noexcept - { - *m_deleted = true; - } + ~ObjectWithWeakRefSample51InitThrow() noexcept + { + *m_deleted = true; + } - friend MakePolicy; // To support private constructor & InitializeThis - friend RefCountPolicy; // To support private destructor + friend MakePolicy; // To support private constructor & InitializeThis + friend RefCountPolicy; // To support private destructor private: - bool* m_deleted { nullptr }; + bool* m_deleted{nullptr}; }; - -TEST_CLASS(ObjectWithWeakRefTest) +TEST_CLASS (ObjectWithWeakRefTest) { - TEST_METHOD(ObjectWithWeakRef_Make) - { - bool deleted = false; - { - Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/deleted); - { - Debug(TestAssert::AreEqual(1u, obj1->GetWeakRef().RefCount())); - TestAssert::AreEqual(5, obj1->Value()); + TEST_METHOD(ObjectWithWeakRef_Make) + { + bool deleted = false; + { + Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/ deleted); + { + Debug(TestAssert::AreEqual(1u, obj1->GetWeakRef().RefCount())); + TestAssert::AreEqual(5, obj1->Value()); - Mso::TCntPtr obj2(obj1); - Debug(TestAssert::AreEqual(2u, obj1->GetWeakRef().RefCount())); - TestAssert::IsNotNull(obj2.Get()); - TestAssert::IsTrue(obj1.Get() == obj2.Get()); - } + Mso::TCntPtr obj2(obj1); + Debug(TestAssert::AreEqual(2u, obj1->GetWeakRef().RefCount())); + TestAssert::IsNotNull(obj2.Get()); + TestAssert::IsTrue(obj1.Get() == obj2.Get()); + } - Debug(TestAssert::AreEqual(1u, obj1->GetWeakRef().RefCount())); - } + Debug(TestAssert::AreEqual(1u, obj1->GetWeakRef().RefCount())); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectWithWeakRef_WeakRef) - { - // Ref count for ObjectWeakRef behaves the same way as for the object. - bool deleted = false; - { - Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/deleted); - Mso::TCntPtr weakRef = &obj1->GetWeakRef(); - { - Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); - Debug(TestAssert::AreEqual(1u, weakRef->WeakRefCount())); + TEST_METHOD(ObjectWithWeakRef_WeakRef) + { + // Ref count for ObjectWeakRef behaves the same way as for the object. + bool deleted = false; + { + Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/ deleted); + Mso::TCntPtr weakRef = &obj1->GetWeakRef(); + { + Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); + Debug(TestAssert::AreEqual(1u, weakRef->WeakRefCount())); - Mso::TCntPtr obj2(obj1); - Debug(TestAssert::AreEqual(3u, weakRef->RefCount())); - } + Mso::TCntPtr obj2(obj1); + Debug(TestAssert::AreEqual(3u, weakRef->RefCount())); + } - Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); - TestAssert::IsFalse(deleted); - TestAssert::IsFalse(weakRef->IsExpired()); - } + Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); + TestAssert::IsFalse(deleted); + TestAssert::IsFalse(weakRef->IsExpired()); + } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectWithWeakRef_WeakPtr) - { - bool deleted = false; - Mso::WeakPtr weakPtr; - { - Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/deleted); - Mso::TCntPtr weakRef = &obj1->GetWeakRef(); - weakPtr = obj1; - { - Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); - Debug(TestAssert::AreEqual(2u, weakRef->WeakRefCount())); + TEST_METHOD(ObjectWithWeakRef_WeakPtr) + { + bool deleted = false; + Mso::WeakPtr weakPtr; + { + Mso::TCntPtr obj1 = Mso::Make(5, /*ref*/ deleted); + Mso::TCntPtr weakRef = &obj1->GetWeakRef(); + weakPtr = obj1; + { + Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); + Debug(TestAssert::AreEqual(2u, weakRef->WeakRefCount())); - Mso::TCntPtr obj2(obj1); - Debug(TestAssert::AreEqual(3u, weakRef->RefCount())); - } + Mso::TCntPtr obj2(obj1); + Debug(TestAssert::AreEqual(3u, weakRef->RefCount())); + } - Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); - TestAssert::IsFalse(deleted); - TestAssert::IsFalse(weakPtr.IsExpired()); - } + Debug(TestAssert::AreEqual(2u, weakRef->RefCount())); + TestAssert::IsFalse(deleted); + TestAssert::IsFalse(weakPtr.IsExpired()); + } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr.IsExpired()); - } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr.IsExpired()); + } + TEST_METHOD(ObjectWithWeakRef_Make_InitializeThis) + { + bool deleted = false; + { + auto obj = Mso::Make(5, /*ref*/ deleted); + Debug(TestAssert::AreEqual(1u, obj->GetWeakRef().RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - TEST_METHOD(ObjectWithWeakRef_Make_InitializeThis) - { - bool deleted = false; - { - auto obj = Mso::Make(5, /*ref*/deleted); - Debug(TestAssert::AreEqual(1u, obj->GetWeakRef().RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TestAssert::IsTrue(deleted); + } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(ObjectWithWeakRef_Make_CannotAllocate) + { + Mso::TCntPtr obj; + TestAssert::ExpectVEC([&]() { obj = Mso::Make(); }); - TEST_METHOD(ObjectWithWeakRef_Make_CannotAllocate) - { - Mso::TCntPtr obj; - TestAssert::ExpectVEC([&]() - { - obj = Mso::Make(); - }); + TestAssert::IsTrue(obj.IsEmpty()); + } - TestAssert::IsTrue(obj.IsEmpty()); - } + TEST_METHOD(ObjectWithWeakRef_Make_CtorThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::Make(/*ref*/ deleted); }); - TEST_METHOD(ObjectWithWeakRef_Make_CtorThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::Make(/*ref*/deleted); - }); + TestAssert::IsFalse(deleted); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TestAssert::IsFalse(deleted); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } + TEST_METHOD(ObjectWithWeakRef_Make_InitializeThisThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::Make(/*ref*/ deleted); }); - TEST_METHOD(ObjectWithWeakRef_Make_InitializeThisThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::Make(/*ref*/deleted); - }); + TestAssert::IsTrue(deleted); // If InitializeThis throws then destructor must be called. + TestAssert::IsTrue(obj.IsEmpty()); + } - TestAssert::IsTrue(deleted); // If InitializeThis throws then destructor must be called. - TestAssert::IsTrue(obj.IsEmpty()); - } + TEST_METHOD(ObjectWithWeakRef_MakeElseNull) + { + bool deleted = false; + { + auto obj = Mso::MakeElseNull(5, /*ref*/ deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - TEST_METHOD(ObjectWithWeakRef_MakeElseNull) - { - bool deleted = false; - { - auto obj = Mso::MakeElseNull(5, /*ref*/deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TestAssert::IsTrue(deleted); + } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(ObjectWithWeakRef_MakeElseNull_InitializeThis) + { + bool deleted = false; + { + auto obj = Mso::MakeElseNull(5, /*ref*/ deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - TEST_METHOD(ObjectWithWeakRef_MakeElseNull_InitializeThis) - { - bool deleted = false; - { - auto obj = Mso::MakeElseNull(5, /*ref*/deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TestAssert::IsTrue(deleted); + } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(ObjectWithWeakRef_MakeElseNull_CannotAllocate) + { + auto obj = Mso::MakeElseNull(); + TestAssert::IsNull(obj.Get()); + } - TEST_METHOD(ObjectWithWeakRef_MakeElseNull_CannotAllocate) - { - auto obj = Mso::MakeElseNull(); - TestAssert::IsNull(obj.Get()); - } + TEST_METHOD(ObjectWithWeakRef_MakeElseNull_CtorThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::MakeElseNull(/*ref*/ deleted); }); + } - TEST_METHOD(ObjectWithWeakRef_MakeElseNull_CtorThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::MakeElseNull(/*ref*/deleted); - }); - } + TEST_METHOD(ObjectWithWeakRef_MakeElseNull_InitializeThisThrows) + { + Mso::TCntPtr obj; + bool deleted = false; + TestAssert::ExpectException( + [&]() { obj = Mso::MakeElseNull(/*ref*/ deleted); }); - TEST_METHOD(ObjectWithWeakRef_MakeElseNull_InitializeThisThrows) - { - Mso::TCntPtr obj; - bool deleted = false; - TestAssert::ExpectException([&]() - { - obj = Mso::MakeElseNull(/*ref*/deleted); - }); + TestAssert::IsTrue(deleted); // If InitializeThis throws then we must call destructor. + TestAssert::IsTrue(obj.IsEmpty()); + } - TestAssert::IsTrue(deleted); // If InitializeThis throws then we must call destructor. - TestAssert::IsTrue(obj.IsEmpty()); - } + struct AllocTestState + { + bool AllocCalled; + bool FreeCalled; + bool Deleted; + }; + static void AssertAllocState(const AllocTestState& state, bool deleted = true) noexcept + { + TestAssert::IsTrue(state.AllocCalled, L"Allocate expected to be called"); + TestAssert::IsTrue(state.FreeCalled, L"Deallocate expected to be called"); + TestAssert::AreEqual(deleted, state.Deleted, L"Destructor to be called"); + } - struct AllocTestState - { - bool AllocCalled; - bool FreeCalled; - bool Deleted; - }; + TEST_METHOD(ObjectWithWeakRef_MakeAlloc) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - static void AssertAllocState(const AllocTestState& state, bool deleted = true) noexcept - { - TestAssert::IsTrue(state.AllocCalled, L"Allocate expected to be called"); - TestAssert::IsTrue(state.FreeCalled, L"Deallocate expected to be called"); - TestAssert::AreEqual(deleted, state.Deleted, L"Destructor to be called"); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectWithWeakRef_MakeAlloc) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectWithWeakRef_MakeAlloc_InitializeThis) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectWithWeakRef_MakeAlloc_InitializeThis) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAlloc(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectWithWeakRef_MakeAlloc_CannotAllocate) + { + Mso::TCntPtr obj; + TestAssert::ExpectVEC([&]() { + AllocTestState state = {}; + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAlloc(&memHeap); + }); - AssertAllocState(state); - } + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectWithWeakRef_MakeAlloc_CannotAllocate) - { - Mso::TCntPtr obj; - TestAssert::ExpectVEC([&]() - { - AllocTestState state = {}; - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAlloc(&memHeap); - }); + TEST_METHOD(ObjectWithWeakRef_MakeAlloc_CtorThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAlloc(&memHeap, /*ref*/ state.Deleted); + }); - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state, /*deleted:*/ false); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectWithWeakRef_MakeAlloc_CtorThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAlloc(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectWithWeakRef_MakeAlloc_InitializeThisThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAlloc(&memHeap, /*ref*/ state.Deleted); + }); - AssertAllocState(state, /*deleted:*/false); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state); // If InitializeThis throws then destructor must be called. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectWithWeakRef_MakeAlloc_InitializeThisThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAlloc(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); // If InitializeThis throws then destructor must be called. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_InitializeThis) + { + AllocTestState state = {}; + { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/ state.Deleted); + Debug(TestAssert::AreEqual(1u, obj->RefCount())); + TestAssert::AreEqual(5, obj->Value()); + } - AssertAllocState(state); - } + AssertAllocState(state); + } - TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_InitializeThis) - { - AllocTestState state = {}; - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAllocElseNull(&memHeap, 5, /*ref*/state.Deleted); - Debug(TestAssert::AreEqual(1u, obj->RefCount())); - TestAssert::AreEqual(5, obj->Value()); - } + TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_CannotAllocate) + { + AllocTestState state = {}; + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + auto obj = Mso::MakeAllocElseNull(&memHeap); + TestAssert::IsNull(obj.Get()); + } - AssertAllocState(state); - } + TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_CtorThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/ state.Deleted); + }); - TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_CannotAllocate) - { - AllocTestState state = {}; - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - auto obj = Mso::MakeAllocElseNull(&memHeap); - TestAssert::IsNull(obj.Get()); - } + AssertAllocState(state, /*deleted:*/ false); // Destructor is not called if constructor throws. + TestAssert::IsTrue(obj.IsEmpty()); + } - TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_CtorThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/state.Deleted); - }); + TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_InitializeThisThrows) + { + Mso::TCntPtr obj; + AllocTestState state = {}; + TestAssert::ExpectException([&]() { + MyMemHeap memHeap(/*ref*/ state.AllocCalled, /*ref*/ state.FreeCalled); + obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/ state.Deleted); + }); - AssertAllocState(state, /*deleted:*/false); // Destructor is not called if constructor throws. - TestAssert::IsTrue(obj.IsEmpty()); - } - - TEST_METHOD(ObjectWithWeakRef_MakeAllocElseNull_InitializeThisThrows) - { - Mso::TCntPtr obj; - AllocTestState state = {}; - TestAssert::ExpectException([&]() - { - MyMemHeap memHeap(/*ref*/state.AllocCalled, /*ref*/state.FreeCalled); - obj = Mso::MakeAllocElseNull(&memHeap, /*ref*/state.Deleted); - }); - - AssertAllocState(state); // If InitializeThis throws then we must call destructor. - TestAssert::IsTrue(obj.IsEmpty()); - } + AssertAllocState(state); // If InitializeThis throws then we must call destructor. + TestAssert::IsTrue(obj.IsEmpty()); + } }; diff --git a/libs/object/tests/queryCastTest.cpp b/libs/object/tests/queryCastTest.cpp index 063d8e5..2a34886 100644 --- a/libs/object/tests/queryCastTest.cpp +++ b/libs/object/tests/queryCastTest.cpp @@ -10,51 +10,56 @@ Unit tests for classes in the ObjectQueryCast.h #include #define DEFINE_STRING_GUID(var, guid) \ - MSO_STRUCT_GUID(_test_##var, guid) \ - struct _test_##var {}; \ - GUID var = __uuidof(_test_##var); + MSO_STRUCT_GUID(_test_##var, guid) \ + struct _test_##var \ + { \ + }; \ + GUID var = __uuidof(_test_##var); MSO_STRUCT_GUID(IQueryCastBase1, "EAE07273-AEFC-4E94-8087-E72F5D028BFC") struct DECLSPEC_NOVTABLE IQueryCastBase1 { - virtual int GetValue1() = 0; + virtual int GetValue1() = 0; }; MSO_STRUCT_GUID(IQueryCastBase2, "D62D6F01-0A54-40C0-9D23-A1C95EAF234D") struct DECLSPEC_NOVTABLE IQueryCastBase2 { - virtual int GetValue2() = 0; + virtual int GetValue2() = 0; }; MSO_STRUCT_GUID(IQueryCastBase3, "54A5CAC7-4788-499E-BAD1-1BBEF60A30F9") struct DECLSPEC_NOVTABLE IQueryCastBase3 { - virtual int GetValue3() = 0; + virtual int GetValue3() = 0; }; MSO_STRUCT_GUID(IQueryCastDerived1, "26747765-CB3C-42BC-8CBE-810F19779169") struct DECLSPEC_NOVTABLE IQueryCastDerived1 : public IQueryCastBase1 { - virtual int GetValue11() = 0; + virtual int GetValue11() = 0; }; class QueryCastTraitsSample1 : public IQueryCastBase1 { public: - virtual int GetValue1() override { return 1; } + virtual int GetValue1() override + { + return 1; + } }; struct QueryCastTraitsBase2 { - void* QueryCast(const GUID& riid) noexcept - { - if (riid == __uuidof(IQueryCastBase1)) - { - return this; - } + void* QueryCast(const GUID& riid) noexcept + { + if (riid == __uuidof(IQueryCastBase1)) + { + return this; + } - return nullptr; - } + return nullptr; + } }; class QueryCastTraitsSample2 : public QueryCastTraitsBase2 @@ -64,91 +69,140 @@ class QueryCastTraitsSample2 : public QueryCastTraitsBase2 MSO_STRUCT_GUID(QueryCastTraitsBase3, "5AF7D77B-7620-403D-9684-98AC591CF1A6") struct QueryCastTraitsBase3 { - void* QueryCast(const GUID& riid) noexcept - { - if (riid == __uuidof(IQueryCastBase1)) - { - return this; - } + void* QueryCast(const GUID& riid) noexcept + { + if (riid == __uuidof(IQueryCastBase1)) + { + return this; + } - return nullptr; - } + return nullptr; + } }; class QueryCastTraitsSample3 : public QueryCastTraitsBase3 { }; -class QueryCastChainSample1 - : public Mso::QueryCastChain +class QueryCastChainSample1 : public Mso::QueryCastChain { public: - virtual int GetValue1() override { return 1; } - virtual int GetValue11() override { return 11; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue11() override + { + return 11; + } }; class QueryCastChainSample2 - : public Mso::QueryCastList, IQueryCastBase2> + : public Mso::QueryCastList, IQueryCastBase2> { public: - virtual int GetValue1() override { return 1; } - virtual int GetValue11() override { return 11; } - virtual int GetValue2() override { return 2; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue11() override + { + return 11; + } + virtual int GetValue2() override + { + return 2; + } }; MSO_CLASS_GUID(QueryCastDerivedSample1, "1B7B2202-8B80-4E08-B20B-85235696BE02") -class QueryCastDerivedSample1 : public Mso::QueryCastList> +class QueryCastDerivedSample1 + : public Mso::QueryCastList> { public: - virtual int GetValue1() override { return 1; } + virtual int GetValue1() override + { + return 1; + } }; DEFINE_STRING_GUID(MyTestGuid1, "65ADDF73-B4EE-4E36-AB61-FEEA1F01A169"); struct DECLSPEC_NOVTABLE IQueryCastNoGuid1 { - virtual int GetValue1() = 0; + virtual int GetValue1() = 0; }; class QueryCastGuidSample1 - : public Mso::QueryCastList, Mso::QueryCastGuid> + : public Mso:: + QueryCastList, Mso::QueryCastGuid> { public: - virtual int GetValue1() override { return 1; } - virtual int GetValue2() override { return 2; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue2() override + { + return 2; + } }; class QueryCastHiddenSample1 : public Mso::QueryCastHidden { public: - virtual int GetValue1() override { return 1; } + virtual int GetValue1() override + { + return 1; + } }; class QueryCastListSample1 : public Mso::QueryCastList { public: - virtual int GetValue1() override { return 1; } + virtual int GetValue1() override + { + return 1; + } }; class QueryCastListSample2 : public Mso::QueryCastList { public: - virtual int GetValue1() override { return 12; } - virtual int GetValue2() override { return 22; } + virtual int GetValue1() override + { + return 12; + } + virtual int GetValue2() override + { + return 22; + } }; class QueryCastListSample3 : public Mso::QueryCastList { public: - virtual int GetValue1() override { return 13; } - virtual int GetValue2() override { return 23; } - virtual int GetValue3() override { return 33; } + virtual int GetValue1() override + { + return 13; + } + virtual int GetValue2() override + { + return 23; + } + virtual int GetValue3() override + { + return 33; + } }; class QueryCastListDerivedSample1 : public Mso::QueryCastList { public: - virtual int GetValue3() override { return 3; } + virtual int GetValue3() override + { + return 3; + } }; struct StaticCastSample1 : public Mso::QueryCastList @@ -161,357 +215,487 @@ struct StaticCastSample1 : public Mso::QueryCastList works for one interface inherited from IUnknown struct StaticSample1 : Mso::QueryCastList { - virtual int GetValue1() override { return 1; } - STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override { return E_NOINTERFACE; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + virtual int GetValue1() override + { + return 1; + } + STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; // To see if StaticCastElseNull works for two interfaces inherited from IUnknown struct StaticSample2 : Mso::QueryCastList { - virtual int GetValue1() override { return 1; } - virtual int GetValue2() override { return 2; } - STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override { return E_NOINTERFACE; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue2() override + { + return 2; + } + STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; // To see if StaticCastElseNull returns nullptr for one interface not inherited from IUnknown struct StaticSample3 : Mso::QueryCastList { - virtual int GetValue3() override { return 3; } + virtual int GetValue3() override + { + return 3; + } }; // To see if StaticCastElseNull returns nullptr for two interfaces not inherited from IUnknown struct StaticSample4 : Mso::QueryCastList { - virtual int GetValue3() override { return 3; } - virtual int GetValue4() override { return 4; } + virtual int GetValue3() override + { + return 3; + } + virtual int GetValue4() override + { + return 4; + } }; // To see if StaticCastElseNull works for two interfaces inherited from IUnknown preceded by // an interface not inherited from IUnknown. struct StaticSample5 : Mso::QueryCastList { - virtual int GetValue1() override { return 1; } - virtual int GetValue2() override { return 2; } - virtual int GetValue3() override { return 3; } - STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override { return E_NOINTERFACE; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue2() override + { + return 2; + } + virtual int GetValue3() override + { + return 3; + } + STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; // To see if StaticCastElseNull works for two interfaces inherited from IUnknown preceded by // two interfaces not inherited from IUnknown. struct StaticSample6 : Mso::QueryCastList { - virtual int GetValue1() override { return 1; } - virtual int GetValue2() override { return 2; } - virtual int GetValue3() override { return 3; } - virtual int GetValue4() override { return 4; } - STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override { return E_NOINTERFACE; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue2() override + { + return 2; + } + virtual int GetValue3() override + { + return 3; + } + virtual int GetValue4() override + { + return 4; + } + STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; // To test nested hierarchy: IUnknown is implemented by nested QueryCastList. -struct StaticSample7 : Mso::QueryCastList> +struct StaticSample7 + : Mso::QueryCastList> { - virtual int GetValue1() override { return 1; } - virtual int GetValue2() override { return 2; } - virtual int GetValue3() override { return 3; } - virtual int GetValue4() override { return 4; } - STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override { return E_NOINTERFACE; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue2() override + { + return 2; + } + virtual int GetValue3() override + { + return 3; + } + virtual int GetValue4() override + { + return 4; + } + STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; // To test nested hierarchy: IUnknown is implemented by nested QueryCastList. -struct StaticSample8 : Mso::QueryCastList, Mso::QueryCastList> +struct StaticSample8 + : Mso::QueryCastList< + Mso::QueryCastList, + Mso::QueryCastList> { - virtual int GetValue1() override { return 1; } - virtual int GetValue2() override { return 2; } - virtual int GetValue3() override { return 3; } - virtual int GetValue4() override { return 4; } - STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override { return E_NOINTERFACE; } - STDMETHOD_(ULONG, AddRef)() noexcept override { return 1; } - STDMETHOD_(ULONG, Release)() noexcept override { return 1; } + virtual int GetValue1() override + { + return 1; + } + virtual int GetValue2() override + { + return 2; + } + virtual int GetValue3() override + { + return 3; + } + virtual int GetValue4() override + { + return 4; + } + STDMETHOD(QueryInterface)(const GUID& /*riid*/, void** /*ppvObject*/) noexcept override + { + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() noexcept override + { + return 1; + } + STDMETHOD_(ULONG, Release)() noexcept override + { + return 1; + } }; // To test nested hierarchy: IUnknown is not implemented. struct StaticSample9 : Mso::QueryCastList> { - virtual int GetValue3() override { return 3; } - virtual int GetValue4() override { return 4; } + virtual int GetValue3() override + { + return 3; + } + virtual int GetValue4() override + { + return 4; + } }; class QueryCastBase1WithArgs : public IQueryCastBase1 { public: - int m_int; - std::string m_string; + int m_int; + std::string m_string; - QueryCastBase1WithArgs(int i, const std::string& str) : m_int(i), m_string(str) {} - virtual int GetValue1() override { return 1; } + QueryCastBase1WithArgs(int i, const std::string& str) : m_int(i), m_string(str) {} + virtual int GetValue1() override + { + return 1; + } }; // Wrapper so that we can call protected constructors template struct StructWithBase : public T { - template - StructWithBase(Args&&... args) : T(std::forward(args)...) {} + template + StructWithBase(Args&&... args) : T(std::forward(args)...) + { + } }; // A helper method to call QueryCastTraits::QueryCast. template -inline TTarget* TraitsQueryCast(const TSource& source, const GUID &riid = __uuidof(TTarget)) noexcept +inline TTarget* TraitsQueryCast(const TSource& source, const GUID& riid = __uuidof(TTarget)) noexcept { - if (source != nullptr) - { - return static_cast(Mso::QueryCastHelper::QueryCast::type>(source, riid)); - } + if (source != nullptr) + { + return static_cast( + Mso::QueryCastHelper::QueryCast::type>(source, riid)); + } - return nullptr; + return nullptr; } TestClassComponent(ObjectQueryCastTest, Mso.ObjectQueryCast) -TEST_CLASS(ObjectQueryCastTest) + TEST_CLASS (ObjectQueryCastTest){// Use GUID by default. + TEST_METHOD(QueryCastTraits_Guid){QueryCastTraitsSample1 obj; + +auto base1 = TraitsQueryCast(&obj); +TestAssert::IsNotNull(base1); +TestAssert::IsTrue((void*)&obj == (void*)base1); + +auto base2 = TraitsQueryCast(&obj, __uuidof(IQueryCastBase2)); +TestAssert::IsNull(base2); +} + +// Use QueryCast method if it is present. +TEST_METHOD(QueryCastTraits_QueryCast) { - // Use GUID by default. - TEST_METHOD(QueryCastTraits_Guid) - { - QueryCastTraitsSample1 obj; + QueryCastTraitsSample2 obj; - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); - TestAssert::IsTrue((void*)&obj == (void*)base1); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base2 = TraitsQueryCast(&obj, __uuidof(IQueryCastBase2)); - TestAssert::IsNull(base2); - } + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNull(base2); +} - // Use QueryCast method if it is present. - TEST_METHOD(QueryCastTraits_QueryCast) - { - QueryCastTraitsSample2 obj; +// QueryCast has higher priority over the assigned GUID. +TEST_METHOD(QueryCastTraits_QueryCastOverridesGuid) +{ + QueryCastTraitsSample3 obj; - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNull(base2); - } + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNull(base2); +} - // QueryCast has higher priority over the assigned GUID. - TEST_METHOD(QueryCastTraits_QueryCastOverridesGuid) - { - QueryCastTraitsSample3 obj; +// Test use of QueryCastChain to query for a base interface. +TEST_METHOD(QueryCastChain_Test) +{ + QueryCastChainSample1 obj; + TestAssert::AreEqual(sizeof(uintptr_t), sizeof(obj), L"There must be only one v-table."); - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNull(base2); - } + auto derived1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(derived1); +} - // Test use of QueryCastChain to query for a base interface. - TEST_METHOD(QueryCastChain_Test) - { - QueryCastChainSample1 obj; - TestAssert::AreEqual(sizeof(uintptr_t), sizeof(obj), L"There must be only one v-table."); +// Test use of QueryCastChain to query for a base interface. +TEST_METHOD(QueryCastChain_InList) +{ + QueryCastChainSample2 obj; + TestAssert::AreEqual(sizeof(uintptr_t) * 2, sizeof(obj), L"There must be only two v-tables."); - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto derived1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(derived1); - } + auto derived1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(derived1); - // Test use of QueryCastChain to query for a base interface. - TEST_METHOD(QueryCastChain_InList) - { - QueryCastChainSample2 obj; - TestAssert::AreEqual(sizeof(uintptr_t) * 2, sizeof(obj), L"There must be only two v-tables."); + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base2); +} - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); +// Test use of QueryCastDerived to query the derived type by its GUID. +TEST_METHOD(QueryCastDerived_Test) +{ + QueryCastDerivedSample1 obj; + TestAssert::AreEqual(sizeof(uintptr_t), sizeof(obj), L"There must be only one v-table."); - auto derived1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(derived1); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base2); - } + auto derived = TraitsQueryCast(&obj); + TestAssert::IsNotNull(derived); +} - // Test use of QueryCastDerived to query the derived type by its GUID. - TEST_METHOD(QueryCastDerived_Test) - { - QueryCastDerivedSample1 obj; - TestAssert::AreEqual(sizeof(uintptr_t), sizeof(obj), L"There must be only one v-table."); +// Test use of QueryCastGuid to query for a base interface. +TEST_METHOD(QueryCastGuid_Test) +{ + QueryCastGuidSample1 obj; + TestAssert::AreEqual(sizeof(uintptr_t) * 2, sizeof(obj), L"There must be only two v-tables."); - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); + auto base1 = TraitsQueryCast(&obj, MyTestGuid1); + TestAssert::IsNotNull(base1); - auto derived = TraitsQueryCast(&obj); - TestAssert::IsNotNull(derived); - } + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base2); +} - // Test use of QueryCastGuid to query for a base interface. - TEST_METHOD(QueryCastGuid_Test) - { - QueryCastGuidSample1 obj; - TestAssert::AreEqual(sizeof(uintptr_t) * 2, sizeof(obj), L"There must be only two v-tables."); +// QueryCastHidden hides the base interface from the query cast. +TEST_METHOD(QueryCastHidden_Test) +{ + QueryCastHiddenSample1 obj; - auto base1 = TraitsQueryCast(&obj, MyTestGuid1); - TestAssert::IsNotNull(base1); + IQueryCastBase1* intf = &obj; + TestAssert::IsNotNull(intf); - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base2); - } + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNull(base1); +} - // QueryCastHidden hides the base interface from the query cast. - TEST_METHOD(QueryCastHidden_Test) - { - QueryCastHiddenSample1 obj; +// Test use of QueryCastList with one base type. +TEST_METHOD(QueryCastList_OneBaseType) +{ + QueryCastListSample1 obj; - IQueryCastBase1* intf = &obj; - TestAssert::IsNotNull(intf); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); +} - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNull(base1); - } +// Test use of QueryCastList with two base types. +TEST_METHOD(QueryCastList_TwoBaseTypes) +{ + QueryCastListSample2 obj; - // Test use of QueryCastList with one base type. - TEST_METHOD(QueryCastList_OneBaseType) - { - QueryCastListSample1 obj; + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); - } + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base2); +} - // Test use of QueryCastList with two base types. - TEST_METHOD(QueryCastList_TwoBaseTypes) - { - QueryCastListSample2 obj; +// Test use of QueryCastList with three base types. +TEST_METHOD(QueryCastList_ThreeBaseTypes) +{ + QueryCastListSample3 obj; - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base2); - } + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base2); - // Test use of QueryCastList with three base types. - TEST_METHOD(QueryCastList_ThreeBaseTypes) - { - QueryCastListSample3 obj; + auto base3 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base3); +} - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); +// Test use of QueryCastList with a type that already inherits from the QueryCastList. +TEST_METHOD(QueryCastList_DerivedQueryCastList) +{ + QueryCastListDerivedSample1 obj; - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base2); + auto base1 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base1); - auto base3 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base3); - } + auto base2 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base2); - // Test use of QueryCastList with a type that already inherits from the QueryCastList. - TEST_METHOD(QueryCastList_DerivedQueryCastList) - { - QueryCastListDerivedSample1 obj; + auto base3 = TraitsQueryCast(&obj); + TestAssert::IsNotNull(base3); +} - auto base1 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base1); +TEST_METHOD(QueryCastList_StaticCast) +{ + StaticCastSample1 obj; - auto base2 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base2); + IQueryCastBase1* base1 = obj.StaticCastElseNull(); + TestAssert::IsNotNull(base1); + TestAssert::AreEqual(12, base1->GetValue1()); - auto base3 = TraitsQueryCast(&obj); - TestAssert::IsNotNull(base3); - } + IQueryCastBase2* base2 = obj.StaticCastElseNull(); + TestAssert::IsNotNull(base2); + TestAssert::AreEqual(22, base2->GetValue2()); - TEST_METHOD(QueryCastList_StaticCast) - { - StaticCastSample1 obj; + IQueryCastBase3* base3 = obj.StaticCastElseNull(); + TestAssert::IsNotNull(base3); + TestAssert::AreEqual(33, base3->GetValue3()); +} - IQueryCastBase1* base1 = obj.StaticCastElseNull(); - TestAssert::IsNotNull(base1); - TestAssert::AreEqual(12, base1->GetValue1()); +TEST_METHOD(QueryCastList_StaticCast2) +{ + StaticSample1 sample1; + StaticSample2 sample2; + StaticSample3 sample3; + StaticSample4 sample4; + StaticSample5 sample5; + StaticSample6 sample6; + StaticSample7 sample7; + StaticSample8 sample8; + StaticSample9 sample9; + TestAssert::IsNotNull(sample1.StaticCastElseNull(), L"sample1"); + TestAssert::IsNotNull(sample2.StaticCastElseNull(), L"sample2"); + TestAssert::IsNull(sample3.StaticCastElseNull(), L"sample3"); + TestAssert::IsNull(sample4.StaticCastElseNull(), L"sample4"); + TestAssert::IsNotNull(sample5.StaticCastElseNull(), L"sample5"); + TestAssert::IsNotNull(sample6.StaticCastElseNull(), L"sample6"); + TestAssert::IsNotNull(sample7.StaticCastElseNull(), L"sample7"); + TestAssert::IsNotNull(sample8.StaticCastElseNull(), L"sample8"); + TestAssert::IsNull(sample9.StaticCastElseNull(), L"sample9"); +} - IQueryCastBase2* base2 = obj.StaticCastElseNull(); - TestAssert::IsNotNull(base2); - TestAssert::AreEqual(22, base2->GetValue2()); +TEST_METHOD(QueryCastChain_ForwardCtorArgs) +{ + StructWithBase> testStruct(5, "asdf"); + TestAssert::AreEqual(5, testStruct.m_int); + TestAssert::AreEqual("asdf", testStruct.m_string.c_str()); +} - IQueryCastBase3* base3 = obj.StaticCastElseNull(); - TestAssert::IsNotNull(base3); - TestAssert::AreEqual(33, base3->GetValue3()); - } +TEST_METHOD(QueryCastGuid_ForwardCtorArgs) +{ + StructWithBase> testStruct(5, "asdf"); + TestAssert::AreEqual(5, testStruct.m_int); + TestAssert::AreEqual("asdf", testStruct.m_string.c_str()); +} - TEST_METHOD(QueryCastList_StaticCast2) - { - StaticSample1 sample1; - StaticSample2 sample2; - StaticSample3 sample3; - StaticSample4 sample4; - StaticSample5 sample5; - StaticSample6 sample6; - StaticSample7 sample7; - StaticSample8 sample8; - StaticSample9 sample9; - TestAssert::IsNotNull(sample1.StaticCastElseNull(), L"sample1"); - TestAssert::IsNotNull(sample2.StaticCastElseNull(), L"sample2"); - TestAssert::IsNull(sample3.StaticCastElseNull(), L"sample3"); - TestAssert::IsNull(sample4.StaticCastElseNull(), L"sample4"); - TestAssert::IsNotNull(sample5.StaticCastElseNull(), L"sample5"); - TestAssert::IsNotNull(sample6.StaticCastElseNull(), L"sample6"); - TestAssert::IsNotNull(sample7.StaticCastElseNull(), L"sample7"); - TestAssert::IsNotNull(sample8.StaticCastElseNull(), L"sample8"); - TestAssert::IsNull(sample9.StaticCastElseNull(), L"sample9"); - } - - TEST_METHOD(QueryCastChain_ForwardCtorArgs) - { - StructWithBase> testStruct(5, "asdf"); - TestAssert::AreEqual(5, testStruct.m_int); - TestAssert::AreEqual("asdf", testStruct.m_string.c_str()); - } - - TEST_METHOD(QueryCastGuid_ForwardCtorArgs) - { - StructWithBase> testStruct(5, "asdf"); - TestAssert::AreEqual(5, testStruct.m_int); - TestAssert::AreEqual("asdf", testStruct.m_string.c_str()); - } - - TEST_METHOD(QueryCastHidden_ForwardCtorArgs) - { - StructWithBase> testStruct(5, "asdf"); - TestAssert::AreEqual(5, testStruct.m_int); - TestAssert::AreEqual("asdf", testStruct.m_string.c_str()); - } -}; +TEST_METHOD(QueryCastHidden_ForwardCtorArgs) +{ + StructWithBase> testStruct(5, "asdf"); + TestAssert::AreEqual(5, testStruct.m_int); + TestAssert::AreEqual("asdf", testStruct.m_string.c_str()); +} +} +; diff --git a/libs/object/tests/refCountedObjectTest.cpp b/libs/object/tests/refCountedObjectTest.cpp index c32e550..8b291e6 100644 --- a/libs/object/tests/refCountedObjectTest.cpp +++ b/libs/object/tests/refCountedObjectTest.cpp @@ -14,967 +14,897 @@ Unit tests for classes in the msoRefCountedObject.h #include //#define TEST_BAD_INHERITANCE1 // Uncomment to see compilation error -//#define TEST_BAD_INHERITANCE2 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this class. +//#define TEST_BAD_INHERITANCE2 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this +//class. struct DECLSPEC_NOVTABLE IRefBaseSample1 : public Mso::IRefCounted { - virtual int GetValue1() = 0; + virtual int GetValue1() = 0; }; struct DECLSPEC_NOVTABLE IRefBaseSample2 : public Mso::IRefCounted { - virtual int GetValue2() = 0; + virtual int GetValue2() = 0; }; // Simple ref counted object that implements one IRefCounted based interface -class RefCountSample1 final - : public Mso::RefCountedObject +class RefCountSample1 final : public Mso::RefCountedObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~RefCountSample1() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample1() noexcept + { + m_deleted = true; + } private: - RefCountSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample1(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Simple ref counted object that implements two IRefCounted based interfaces -class RefCountSample2 final - : public Mso::RefCountedObject +class RefCountSample2 final : public Mso::RefCountedObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } protected: - virtual ~RefCountSample2() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample2() noexcept + { + m_deleted = true; + } private: - RefCountSample2(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample2(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Ref counted object that supports weak reference and implements one IRefCounted based interface. -class RefCountSample3 final - : public Mso::RefCountedObject +class RefCountSample3 final : public Mso::RefCountedObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~RefCountSample3() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample3() noexcept + { + m_deleted = true; + } private: - RefCountSample3(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample3(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Ref counted object that supports weak reference and implements two IRefCounted based interfaces. class RefCountSample4 final - : public Mso::RefCountedObject + : public Mso::RefCountedObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } protected: - virtual ~RefCountSample4() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample4() noexcept + { + m_deleted = true; + } private: - RefCountSample4(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample4(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Object that does not have ref count and implements one IRefCounted based interface. -class RefCountSample5 final - : public Mso::RefCountedObject +class RefCountSample5 final : public Mso::RefCountedObject { public: - RefCountSample5(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample5(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual ~RefCountSample5() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample5() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; // Object that does not have ref count and implements two IRefCounted based interfaces. class RefCountSample6 final - : public Mso::RefCountedObject + : public Mso::RefCountedObject { public: - RefCountSample6(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample6(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } - virtual ~RefCountSample6() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample6() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; // Simple ref counted object without V-table -class RefCountSample7 final - : public Mso::RefCountedObjectNoVTable +class RefCountSample7 final : public Mso::RefCountedObjectNoVTable { - friend MakePolicy; // To allow constructor to be private or protected. - friend RefCountPolicy; // Allow it to call our destructor + friend MakePolicy; // To allow constructor to be private or protected. + friend RefCountPolicy; // Allow it to call our destructor public: - int GetValue1() noexcept - { - OACR_USE_PTR(this); - return 1; - } + int GetValue1() noexcept + { + OACR_USE_PTR(this); + return 1; + } protected: - ~RefCountSample7() noexcept - { - m_deleted = true; - } + ~RefCountSample7() noexcept + { + m_deleted = true; + } private: - RefCountSample7(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample7(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Object that supports weak ref and has no V-table -class RefCountSample8 final - : public Mso::RefCountedObjectNoVTable +class RefCountSample8 final : public Mso::RefCountedObjectNoVTable { - friend MakePolicy; // To allow constructor to be private or protected. - friend RefCountPolicy; // Allow it to call our destructor + friend MakePolicy; // To allow constructor to be private or protected. + friend RefCountPolicy; // Allow it to call our destructor public: - int GetValue1() noexcept - { - OACR_USE_PTR(this); - return 1; - } + int GetValue1() noexcept + { + OACR_USE_PTR(this); + return 1; + } protected: - ~RefCountSample8() noexcept - { - m_deleted = true; - } + ~RefCountSample8() noexcept + { + m_deleted = true; + } private: - RefCountSample8(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample8(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; /// Base class for RefCountedObject that implements one interface and has non-default constructors. class RefCountSample9Base : public IRefBaseSample1 { public: - virtual int GetValue1() noexcept override - { - return m_param0 + m_param1 + m_param2; - } + virtual int GetValue1() noexcept override + { + return m_param0 + m_param1 + m_param2; + } protected: - RefCountSample9Base() = default; - RefCountSample9Base(int param0) noexcept : m_param0(param0) {} - RefCountSample9Base(int param0, int param1) noexcept : m_param0(param0), m_param1(param1) {} - RefCountSample9Base(int param0, int param1, int param2) noexcept : m_param0(param0), m_param1(param1), m_param2(param2) {} + RefCountSample9Base() = default; + RefCountSample9Base(int param0) noexcept : m_param0(param0) {} + RefCountSample9Base(int param0, int param1) noexcept : m_param0(param0), m_param1(param1) {} + RefCountSample9Base(int param0, int param1, int param2) noexcept + : m_param0(param0), m_param1(param1), m_param2(param2) + { + } private: - int m_param0 = 0; - int m_param1 = 0; - int m_param2 = 0; + int m_param0 = 0; + int m_param1 = 0; + int m_param2 = 0; }; /// Simple ref counted object inherited from RefCountSample9Base with non-default constructors. -class RefCountSample91 final - : public Mso::RefCountedObject +class RefCountSample91 final : public Mso::RefCountedObject { - using Super = RefCountedObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = RefCountedObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue2() noexcept override - { - return 1; - } + virtual int GetValue2() noexcept override + { + return 1; + } protected: - virtual ~RefCountSample91() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample91() noexcept + { + m_deleted = true; + } private: - RefCountSample91(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample91(bool& deleted) noexcept : m_deleted(deleted) {} - RefCountSample91(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + RefCountSample91(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - RefCountSample91(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + RefCountSample91(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - RefCountSample91(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + RefCountSample91(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } private: - bool& m_deleted; + bool& m_deleted; }; /// Object with a weak reference inherited from RefCountSample9Base with non-default constructors. class RefCountSample92 final - : public Mso::RefCountedObject + : public Mso::RefCountedObject { - using Super = RefCountedObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = RefCountedObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue2() noexcept override - { - return 1; - } + virtual int GetValue2() noexcept override + { + return 1; + } protected: - virtual ~RefCountSample92() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample92() noexcept + { + m_deleted = true; + } private: - RefCountSample92(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample92(bool& deleted) noexcept : m_deleted(deleted) {} - RefCountSample92(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + RefCountSample92(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - RefCountSample92(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + RefCountSample92(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - RefCountSample92(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + RefCountSample92(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } private: - bool& m_deleted; + bool& m_deleted; }; /// Object without reference counting and inherited from RefCountSample9Base with non-default constructors. class RefCountSample93 final - : public Mso::RefCountedObject + : public Mso::RefCountedObject { - using Super = RefCountedObjectType; + using Super = RefCountedObjectType; public: - RefCountSample93(bool& deleted) noexcept - : m_deleted(deleted) - { - } + RefCountSample93(bool& deleted) noexcept : m_deleted(deleted) {} - RefCountSample93(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + RefCountSample93(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - RefCountSample93(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + RefCountSample93(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - RefCountSample93(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + RefCountSample93(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } - virtual int GetValue2() noexcept override - { - return 1; - } + virtual int GetValue2() noexcept override + { + return 1; + } - virtual ~RefCountSample93() noexcept - { - m_deleted = true; - } + virtual ~RefCountSample93() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; struct AsyncDeleter { - template - static void Delete(TObject* obj) noexcept - { - // Destroy object asynchronously - obj->SetAsyncDestroy(); - try - { - // Ideally we want to show here how to use dispatch queues, but we cannot add DispatchQueue liblet dependency here. - std::thread([obj]() noexcept { TObject::RefCountPolicy::template Delete(obj); }).detach(); - } - catch (...) - { - VerifyElseCrashTag(false, 0x01003707 /* tag_bad2h */); - } - } + template + static void Delete(TObject* obj) noexcept + { + // Destroy object asynchronously + obj->SetAsyncDestroy(); + try + { + // Ideally we want to show here how to use dispatch queues, but we cannot add DispatchQueue liblet dependency + // here. + std::thread([obj]() noexcept { TObject::RefCountPolicy::template Delete(obj); }).detach(); + } + catch (...) + { + VerifyElseCrashTag(false, 0x01003707 /* tag_bad2h */); + } + } }; MSO_STRUCT_GUID(ITestAsyncDestroy, "18cd4582-2a30-4cdb-94c7-cf8d310101b8") struct ITestAsyncDestroy { - virtual void SetAsyncDestroy() noexcept = 0; + virtual void SetAsyncDestroy() noexcept = 0; }; // To test custom DestroyThis method class RefCountSample101 final - : public Mso::RefCountedObject, IRefBaseSample1, ITestAsyncDestroy> + : public Mso::RefCountedObject, IRefBaseSample1, ITestAsyncDestroy> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual void SetAsyncDestroy() noexcept override - { - m_isAsyncDestroy = true; - } + virtual void SetAsyncDestroy() noexcept override + { + m_isAsyncDestroy = true; + } protected: - virtual ~RefCountSample101() noexcept - { - m_deleted.Set(); - } + virtual ~RefCountSample101() noexcept + { + m_deleted.Set(); + } private: - RefCountSample101(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept - : m_deleted(deleted) - , m_isAsyncDestroy(isAsyncDestroy) - { - } + RefCountSample101(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept + : m_deleted(deleted), m_isAsyncDestroy(isAsyncDestroy) + { + } private: - Mso::Async::ManualResetEvent m_deleted; - bool& m_isAsyncDestroy; + Mso::Async::ManualResetEvent m_deleted; + bool& m_isAsyncDestroy; }; // To test custom DestroyThis method class RefCountSample102 final - : public Mso::RefCountedObject, IRefBaseSample1, ITestAsyncDestroy> + : public Mso::RefCountedObject, IRefBaseSample1, ITestAsyncDestroy> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual void SetAsyncDestroy() noexcept override - { - m_isAsyncDestroy = true; - } + virtual void SetAsyncDestroy() noexcept override + { + m_isAsyncDestroy = true; + } protected: - virtual ~RefCountSample102() noexcept - { - m_deleted.Set(); - } + virtual ~RefCountSample102() noexcept + { + m_deleted.Set(); + } private: - RefCountSample102(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept - : m_deleted(deleted) - , m_isAsyncDestroy(isAsyncDestroy) - { - } + RefCountSample102(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept + : m_deleted(deleted), m_isAsyncDestroy(isAsyncDestroy) + { + } private: - Mso::Async::ManualResetEvent m_deleted; - bool& m_isAsyncDestroy; + Mso::Async::ManualResetEvent m_deleted; + bool& m_isAsyncDestroy; }; // To test custom DestroyThis method class RefCountSample103 final - : public Mso::RefCountedObjectNoVTable, RefCountSample103> + : public Mso::RefCountedObjectNoVTable, RefCountSample103> { - friend MakePolicy; // To allow constructor to be private or protected. - friend RefCountPolicy; // Allow it to call our destructor. + friend MakePolicy; // To allow constructor to be private or protected. + friend RefCountPolicy; // Allow it to call our destructor. public: - int GetValue1() noexcept - { - OACR_USE_PTR(this); - return 1; - } + int GetValue1() noexcept + { + OACR_USE_PTR(this); + return 1; + } - void SetAsyncDestroy() noexcept - { - m_isAsyncDestroy = true; - } + void SetAsyncDestroy() noexcept + { + m_isAsyncDestroy = true; + } protected: - ~RefCountSample103() noexcept - { - m_deleted.Set(); - } + ~RefCountSample103() noexcept + { + m_deleted.Set(); + } private: - RefCountSample103(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept - : m_deleted(deleted) - , m_isAsyncDestroy(isAsyncDestroy) - { - } + RefCountSample103(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept + : m_deleted(deleted), m_isAsyncDestroy(isAsyncDestroy) + { + } private: - Mso::Async::ManualResetEvent m_deleted; - bool& m_isAsyncDestroy; + Mso::Async::ManualResetEvent m_deleted; + bool& m_isAsyncDestroy; }; // To test custom DestroyThis method class RefCountSample104 final - : public Mso::RefCountedObjectNoVTable, RefCountSample104> + : public Mso::RefCountedObjectNoVTable, RefCountSample104> { - friend MakePolicy; // To allow constructor to be private or protected. - friend RefCountPolicy; // Allow it to call our destructor. + friend MakePolicy; // To allow constructor to be private or protected. + friend RefCountPolicy; // Allow it to call our destructor. public: - int GetValue1() noexcept - { - OACR_USE_PTR(this); - return 1; - } + int GetValue1() noexcept + { + OACR_USE_PTR(this); + return 1; + } - void SetAsyncDestroy() noexcept - { - m_isAsyncDestroy = true; - } + void SetAsyncDestroy() noexcept + { + m_isAsyncDestroy = true; + } protected: - ~RefCountSample104() noexcept - { - m_deleted.Set(); - } + ~RefCountSample104() noexcept + { + m_deleted.Set(); + } private: - RefCountSample104(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept - : m_deleted(deleted) - , m_isAsyncDestroy(isAsyncDestroy) - { - } + RefCountSample104(const Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept + : m_deleted(deleted), m_isAsyncDestroy(isAsyncDestroy) + { + } private: - Mso::Async::ManualResetEvent m_deleted; - bool& m_isAsyncDestroy; + Mso::Async::ManualResetEvent m_deleted; + bool& m_isAsyncDestroy; }; class SomeVirtualClass { public: - virtual ~SomeVirtualClass() = default; + virtual ~SomeVirtualClass() = default; - int x; - int y; + int x; + int y; }; #ifdef TEST_BAD_INHERITANCE1 // !!! Mso::RefCountedObject must be always the first one in the inheritance !!! class BadRefCountedObject1 final - : public SomeVirtualClass - , public Mso::RefCountedObject + : public SomeVirtualClass + , public Mso::RefCountedObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(BadRefCountedObject1); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(BadRefCountedObject1); - virtual int GetValue1() override - { - return 1; - } + virtual int GetValue1() override + { + return 1; + } private: - BadRefCountedObject1() = default; + BadRefCountedObject1() = default; }; #endif #ifdef TEST_BAD_INHERITANCE2 // !!! Mso::RefCountedObject must be always the first one in the inheritance !!! class BadRefCountedObject2 final - : public SomeVirtualClass - , public Mso::RefCountedObject + : public SomeVirtualClass + , public Mso::RefCountedObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() override - { - return 1; - } + virtual int GetValue1() override + { + return 1; + } private: - BadRefCountedObject2() = default; - + BadRefCountedObject2() = default; }; #endif -TEST_CLASS(RefCountedObjectTest) +TEST_CLASS (RefCountedObjectTest) { - TEST_METHOD(RefCountedObject_SimpleRefCount) - { - bool deleted = false; - { - Mso::TCntPtr refCounted = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, refCounted->GetValue1()); - Debug(TestAssert::AreEqual(1, refCounted->RefCount())); + TEST_METHOD(RefCountedObject_SimpleRefCount) + { + bool deleted = false; + { + Mso::TCntPtr refCounted = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, refCounted->GetValue1()); + Debug(TestAssert::AreEqual(1, refCounted->RefCount())); - Mso::TCntPtr base1 = refCounted; - TestAssert::AreEqual(1,base1->GetValue1()); - Debug(TestAssert::AreEqual(2, refCounted->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base1 = refCounted; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, refCounted->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_SimpleRefCount2) - { - bool deleted = false; - { - Mso::TCntPtr refCounted = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, refCounted->GetValue1()); - Debug(TestAssert::AreEqual(1, refCounted->RefCount())); + TEST_METHOD(RefCountedObject_SimpleRefCount2) + { + bool deleted = false; + { + Mso::TCntPtr refCounted = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, refCounted->GetValue1()); + Debug(TestAssert::AreEqual(1, refCounted->RefCount())); - Mso::TCntPtr base1 = refCounted; - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, refCounted->RefCount())); + Mso::TCntPtr base1 = refCounted; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, refCounted->RefCount())); - Mso::TCntPtr base2 = refCounted; - TestAssert::AreEqual(2, base2->GetValue2()); - Debug(TestAssert::AreEqual(3, refCounted->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base2 = refCounted; + TestAssert::AreEqual(2, base2->GetValue2()); + Debug(TestAssert::AreEqual(3, refCounted->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_WeakRefCount) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr1; - Mso::WeakPtr weakPtrBase1; - { - Mso::TCntPtr refCounted = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = refCounted; - TestAssert::AreEqual(1, base1->GetValue1()); + TEST_METHOD(RefCountedObject_WeakRefCount) + { + bool deleted = false; + { + Mso::WeakPtr weakPtr1; + Mso::WeakPtr weakPtrBase1; + { + Mso::TCntPtr refCounted = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = refCounted; + TestAssert::AreEqual(1, base1->GetValue1()); - weakPtr1 = refCounted; - Mso::TCntPtr refCounted1 = weakPtr1.GetStrongPtr(); - TestAssert::IsNotNull(refCounted1.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); + weakPtr1 = refCounted; + Mso::TCntPtr refCounted1 = weakPtr1.GetStrongPtr(); + TestAssert::IsNotNull(refCounted1.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); - weakPtrBase1 = refCounted; - Mso::TCntPtr base11 = weakPtrBase1.GetStrongPtr(); - TestAssert::IsNotNull(base11.Get()); - TestAssert::IsFalse(weakPtrBase1.IsExpired()); - } + weakPtrBase1 = refCounted; + Mso::TCntPtr base11 = weakPtrBase1.GetStrongPtr(); + TestAssert::IsNotNull(base11.Get()); + TestAssert::IsFalse(weakPtrBase1.IsExpired()); + } - TestAssert::IsTrue(deleted); + TestAssert::IsTrue(deleted); - Mso::TCntPtr refCounted11 = weakPtr1.GetStrongPtr(); - TestAssert::IsNull(refCounted11.Get()); - TestAssert::IsTrue(weakPtr1.IsExpired()); + Mso::TCntPtr refCounted11 = weakPtr1.GetStrongPtr(); + TestAssert::IsNull(refCounted11.Get()); + TestAssert::IsTrue(weakPtr1.IsExpired()); - Mso::TCntPtr base111 = weakPtrBase1.GetStrongPtr(); - TestAssert::IsNull(base111.Get()); - TestAssert::IsTrue(weakPtrBase1.IsExpired()); - } - } + Mso::TCntPtr base111 = weakPtrBase1.GetStrongPtr(); + TestAssert::IsNull(base111.Get()); + TestAssert::IsTrue(weakPtrBase1.IsExpired()); + } + } - TEST_METHOD(RefCountedObject_WeakRefCount2) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr1; - Mso::WeakPtr weakPtrBase1; - Mso::WeakPtr weakPtrBase2; - { - Mso::TCntPtr refCounted = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = refCounted; - TestAssert::AreEqual(1, base1->GetValue1()); - Mso::TCntPtr base2 = refCounted; - TestAssert::AreEqual(2, base2->GetValue2()); + TEST_METHOD(RefCountedObject_WeakRefCount2) + { + bool deleted = false; + { + Mso::WeakPtr weakPtr1; + Mso::WeakPtr weakPtrBase1; + Mso::WeakPtr weakPtrBase2; + { + Mso::TCntPtr refCounted = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = refCounted; + TestAssert::AreEqual(1, base1->GetValue1()); + Mso::TCntPtr base2 = refCounted; + TestAssert::AreEqual(2, base2->GetValue2()); - weakPtr1 = refCounted; - Mso::TCntPtr refCounted1 = weakPtr1.GetStrongPtr(); - TestAssert::IsNotNull(refCounted1.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); + weakPtr1 = refCounted; + Mso::TCntPtr refCounted1 = weakPtr1.GetStrongPtr(); + TestAssert::IsNotNull(refCounted1.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); - weakPtrBase1 = refCounted; - Mso::TCntPtr base11 = weakPtrBase1.GetStrongPtr(); - TestAssert::IsNotNull(base11.Get()); - TestAssert::IsFalse(weakPtrBase1.IsExpired()); + weakPtrBase1 = refCounted; + Mso::TCntPtr base11 = weakPtrBase1.GetStrongPtr(); + TestAssert::IsNotNull(base11.Get()); + TestAssert::IsFalse(weakPtrBase1.IsExpired()); - weakPtrBase2 = refCounted; - Mso::TCntPtr base21 = weakPtrBase2.GetStrongPtr(); - TestAssert::IsNotNull(base21.Get()); - TestAssert::IsFalse(weakPtrBase2.IsExpired()); - } + weakPtrBase2 = refCounted; + Mso::TCntPtr base21 = weakPtrBase2.GetStrongPtr(); + TestAssert::IsNotNull(base21.Get()); + TestAssert::IsFalse(weakPtrBase2.IsExpired()); + } - TestAssert::IsTrue(deleted); + TestAssert::IsTrue(deleted); - Mso::TCntPtr refCounted11 = weakPtr1.GetStrongPtr(); - TestAssert::IsNull(refCounted11.Get()); - TestAssert::IsTrue(weakPtr1.IsExpired()); + Mso::TCntPtr refCounted11 = weakPtr1.GetStrongPtr(); + TestAssert::IsNull(refCounted11.Get()); + TestAssert::IsTrue(weakPtr1.IsExpired()); - Mso::TCntPtr base111 = weakPtrBase1.GetStrongPtr(); - TestAssert::IsNull(base111.Get()); - TestAssert::IsTrue(weakPtrBase1.IsExpired()); + Mso::TCntPtr base111 = weakPtrBase1.GetStrongPtr(); + TestAssert::IsNull(base111.Get()); + TestAssert::IsTrue(weakPtrBase1.IsExpired()); - Mso::TCntPtr base211 = weakPtrBase2.GetStrongPtr(); - TestAssert::IsNull(base211.Get()); - TestAssert::IsTrue(weakPtrBase2.IsExpired()); - } - } + Mso::TCntPtr base211 = weakPtrBase2.GetStrongPtr(); + TestAssert::IsNull(base211.Get()); + TestAssert::IsTrue(weakPtrBase2.IsExpired()); + } + } - TEST_METHOD(RefCountedObject_NoRefCount) - { - bool deleted = false; - { - RefCountSample5 obj(/*ref*/deleted); // Stack allocation - Mso::TCntPtr refCounted(&obj); - TestAssert::AreEqual(1, refCounted->GetValue1()); + TEST_METHOD(RefCountedObject_NoRefCount) + { + bool deleted = false; + { + RefCountSample5 obj(/*ref*/ deleted); // Stack allocation + Mso::TCntPtr refCounted(&obj); + TestAssert::AreEqual(1, refCounted->GetValue1()); - Mso::TCntPtr base1 = refCounted; - TestAssert::AreEqual(1, base1->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base1 = refCounted; + TestAssert::AreEqual(1, base1->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_NoRefCount2) - { - bool deleted = false; - { - RefCountSample6 obj(/*ref*/deleted); // Stack allocation - Mso::TCntPtr refCounted(&obj); - TestAssert::AreEqual(1, refCounted->GetValue1()); + TEST_METHOD(RefCountedObject_NoRefCount2) + { + bool deleted = false; + { + RefCountSample6 obj(/*ref*/ deleted); // Stack allocation + Mso::TCntPtr refCounted(&obj); + TestAssert::AreEqual(1, refCounted->GetValue1()); - Mso::TCntPtr base1 = refCounted; - TestAssert::AreEqual(1, base1->GetValue1()); + Mso::TCntPtr base1 = refCounted; + TestAssert::AreEqual(1, base1->GetValue1()); - Mso::TCntPtr base2 = refCounted; - TestAssert::AreEqual(2, base2->GetValue2()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base2 = refCounted; + TestAssert::AreEqual(2, base2->GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_DestroyThis) - { - Mso::Async::ManualResetEvent deleted; - bool isAsyncDestroy = false; + TEST_METHOD(RefCountedObject_DestroyThis) + { + Mso::Async::ManualResetEvent deleted; + bool isAsyncDestroy = false; - { - Mso::TCntPtr obj1 = Mso::Make(/*ref*/deleted, /*ref*/isAsyncDestroy); - Mso::TCntPtr base1 = obj1.Get(); - TestAssert::AreEqual(1, base1->GetValue1()); - } + { + Mso::TCntPtr obj1 = Mso::Make(/*ref*/ deleted, /*ref*/ isAsyncDestroy); + Mso::TCntPtr base1 = obj1.Get(); + TestAssert::AreEqual(1, base1->GetValue1()); + } - // Wait for deletion to complete - deleted.Wait(); - TestAssert::IsTrue(isAsyncDestroy); - } + // Wait for deletion to complete + deleted.Wait(); + TestAssert::IsTrue(isAsyncDestroy); + } - TEST_METHOD(RefCountedObject_WeakRef_DestroyThis) - { - Mso::Async::ManualResetEvent deleted; - bool isAsyncDestroy = false; + TEST_METHOD(RefCountedObject_WeakRef_DestroyThis) + { + Mso::Async::ManualResetEvent deleted; + bool isAsyncDestroy = false; - { - Mso::TCntPtr obj1 = Mso::Make(/*ref*/deleted, /*ref*/isAsyncDestroy); - Mso::TCntPtr base1 = obj1.Get(); - TestAssert::AreEqual(1, base1->GetValue1()); - } + { + Mso::TCntPtr obj1 = Mso::Make(/*ref*/ deleted, /*ref*/ isAsyncDestroy); + Mso::TCntPtr base1 = obj1.Get(); + TestAssert::AreEqual(1, base1->GetValue1()); + } - // Wait for deletion to complete - deleted.Wait(); - TestAssert::IsTrue(isAsyncDestroy); - } + // Wait for deletion to complete + deleted.Wait(); + TestAssert::IsTrue(isAsyncDestroy); + } - TEST_METHOD(RefCountedObject_NoVTable_DestroyThis) - { - Mso::Async::ManualResetEvent deleted; - bool isAsyncDestroy = false; + TEST_METHOD(RefCountedObject_NoVTable_DestroyThis) + { + Mso::Async::ManualResetEvent deleted; + bool isAsyncDestroy = false; - { - Mso::TCntPtr obj1 = Mso::Make(/*ref*/deleted, /*ref*/isAsyncDestroy); - TestAssert::AreEqual(1, obj1->GetValue1()); - } + { + Mso::TCntPtr obj1 = Mso::Make(/*ref*/ deleted, /*ref*/ isAsyncDestroy); + TestAssert::AreEqual(1, obj1->GetValue1()); + } - // Wait for deletion to complete - deleted.Wait(); - TestAssert::IsTrue(isAsyncDestroy); - } + // Wait for deletion to complete + deleted.Wait(); + TestAssert::IsTrue(isAsyncDestroy); + } - TEST_METHOD(RefCountedObject_NoVTable_WeakRef_DestroyThis) - { - Mso::Async::ManualResetEvent deleted; - bool isAsyncDestroy = false; + TEST_METHOD(RefCountedObject_NoVTable_WeakRef_DestroyThis) + { + Mso::Async::ManualResetEvent deleted; + bool isAsyncDestroy = false; - { - Mso::TCntPtr obj1 = Mso::Make(/*ref*/deleted, /*ref*/isAsyncDestroy); - TestAssert::AreEqual(1, obj1->GetValue1()); - } + { + Mso::TCntPtr obj1 = Mso::Make(/*ref*/ deleted, /*ref*/ isAsyncDestroy); + TestAssert::AreEqual(1, obj1->GetValue1()); + } - // Wait for deletion to complete - deleted.Wait(); - TestAssert::IsTrue(isAsyncDestroy); - } + // Wait for deletion to complete + deleted.Wait(); + TestAssert::IsTrue(isAsyncDestroy); + } - TEST_METHOD(RefCountedObject_NoVTable_SimpleRefCount) - { - bool deleted = false; - { - Mso::TCntPtr refCounted1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, refCounted1->GetValue1()); - Debug(TestAssert::AreEqual(1, refCounted1->RefCount())); - Mso::TCntPtr refCounted2(refCounted1); - UNREFERENCED_OACR(refCounted2); - Debug(TestAssert::AreEqual(2, refCounted1->RefCount())); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(RefCountedObject_NoVTable_SimpleRefCount) + { + bool deleted = false; + { + Mso::TCntPtr refCounted1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, refCounted1->GetValue1()); + Debug(TestAssert::AreEqual(1, refCounted1->RefCount())); + Mso::TCntPtr refCounted2(refCounted1); + UNREFERENCED_OACR(refCounted2); + Debug(TestAssert::AreEqual(2, refCounted1->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_NoVTable_WeakRefCount) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr1; - { - Mso::TCntPtr refCounted = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, refCounted->GetValue1()); + TEST_METHOD(RefCountedObject_NoVTable_WeakRefCount) + { + bool deleted = false; + { + Mso::WeakPtr weakPtr1; + { + Mso::TCntPtr refCounted = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, refCounted->GetValue1()); - weakPtr1 = refCounted; - Mso::TCntPtr refCounted1 = weakPtr1.GetStrongPtr(); - TestAssert::IsNotNull(refCounted1.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); - } + weakPtr1 = refCounted; + Mso::TCntPtr refCounted1 = weakPtr1.GetStrongPtr(); + TestAssert::IsNotNull(refCounted1.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); + } - TestAssert::IsTrue(deleted); + TestAssert::IsTrue(deleted); - Mso::TCntPtr refCounted11 = weakPtr1.GetStrongPtr(); - TestAssert::IsNull(refCounted11.Get()); - TestAssert::IsTrue(weakPtr1.IsExpired()); - } - } + Mso::TCntPtr refCounted11 = weakPtr1.GetStrongPtr(); + TestAssert::IsNull(refCounted11.Get()); + TestAssert::IsTrue(weakPtr1.IsExpired()); + } + } - TEST_METHOD(RefCountedObject_NonDefaultBaseConstructor) - { - bool deleted = false; - { - Mso::TCntPtr refCounted1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = refCounted1.Get(); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(RefCountedObject_NonDefaultBaseConstructor) + { + bool deleted = false; + { + Mso::TCntPtr refCounted1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = refCounted1.Get(); + TestAssert::AreEqual(0, base1->GetValue1()); - Mso::TCntPtr refCounted2 = Mso::Make(/*ref*/deleted, 3); - Mso::TCntPtr base2 = refCounted2.Get(); - TestAssert::AreEqual(3, base2->GetValue1()); + Mso::TCntPtr refCounted2 = Mso::Make(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = refCounted2.Get(); + TestAssert::AreEqual(3, base2->GetValue1()); - Mso::TCntPtr refCounted3 = Mso::Make(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = refCounted3.Get(); - TestAssert::AreEqual(8, base3->GetValue1()); + Mso::TCntPtr refCounted3 = Mso::Make(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = refCounted3.Get(); + TestAssert::AreEqual(8, base3->GetValue1()); - Mso::TCntPtr refCounted4 = Mso::Make(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = refCounted4.Get(); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr refCounted4 = Mso::Make(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = refCounted4.Get(); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_WeakRef_NonDefaultBaseConstructor) - { - bool deleted = false; - { - Mso::TCntPtr refCounted1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = refCounted1.Get(); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(RefCountedObject_WeakRef_NonDefaultBaseConstructor) + { + bool deleted = false; + { + Mso::TCntPtr refCounted1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = refCounted1.Get(); + TestAssert::AreEqual(0, base1->GetValue1()); - Mso::TCntPtr refCounted2 = Mso::Make(/*ref*/deleted, 3); - Mso::TCntPtr base2 = refCounted2.Get(); - TestAssert::AreEqual(3, base2->GetValue1()); + Mso::TCntPtr refCounted2 = Mso::Make(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = refCounted2.Get(); + TestAssert::AreEqual(3, base2->GetValue1()); - Mso::TCntPtr refCounted3 = Mso::Make(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = refCounted3.Get(); - TestAssert::AreEqual(8, base3->GetValue1()); + Mso::TCntPtr refCounted3 = Mso::Make(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = refCounted3.Get(); + TestAssert::AreEqual(8, base3->GetValue1()); - Mso::TCntPtr refCounted4 = Mso::Make(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = refCounted4.Get(); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr refCounted4 = Mso::Make(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = refCounted4.Get(); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(RefCountedObject_NoRefCount_NonDefaultBaseConstructor) - { - bool deleted = false; - { - RefCountSample93 refCounted1(/*ref*/deleted); - Mso::TCntPtr base1 = &refCounted1; - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(RefCountedObject_NoRefCount_NonDefaultBaseConstructor) + { + bool deleted = false; + { + RefCountSample93 refCounted1(/*ref*/ deleted); + Mso::TCntPtr base1 = &refCounted1; + TestAssert::AreEqual(0, base1->GetValue1()); - RefCountSample93 refCounted2(/*ref*/deleted, 3); - Mso::TCntPtr base2 = &refCounted2; - TestAssert::AreEqual(3, base2->GetValue1()); + RefCountSample93 refCounted2(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = &refCounted2; + TestAssert::AreEqual(3, base2->GetValue1()); - RefCountSample93 refCounted3(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = &refCounted3; - TestAssert::AreEqual(8, base3->GetValue1()); + RefCountSample93 refCounted3(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = &refCounted3; + TestAssert::AreEqual(8, base3->GetValue1()); - RefCountSample93 refCounted4(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = &refCounted4; - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + RefCountSample93 refCounted4(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = &refCounted4; + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } #if defined(DEBUG) && defined(TEST_BAD_INHERITANCE1) - TESTMETHOD_REQUIRES_SEH(RefCountedObject_BadInheritance1) - { - TestAssert::ExpectVEC([&]() noexcept - { - // This code must not compile, but if we remove the static assert from ObjectRefCount.h then we must have VEC here. - // You will see a memory leak here because we cannot destroy object correctly. - Mso::Make(); - }); - } + TESTMETHOD_REQUIRES_SEH(RefCountedObject_BadInheritance1) + { + TestAssert::ExpectVEC([&]() noexcept { + // This code must not compile, but if we remove the static assert from ObjectRefCount.h then we must have VEC + // here. You will see a memory leak here because we cannot destroy object correctly. + Mso::Make(); + }); + } #endif #if defined(DEBUG) && defined(TEST_BAD_INHERITANCE2) - TESTMETHOD_REQUIRES_SEH(RefCountedObject_BadInheritance2) - { - TestAssert::ExpectVEC([&]() noexcept - { - // You will see a memory leak here because we cannot destroy object correctly. - Mso::Make(); - }); - } + TESTMETHOD_REQUIRES_SEH(RefCountedObject_BadInheritance2) + { + TestAssert::ExpectVEC([&]() noexcept { + // You will see a memory leak here because we cannot destroy object correctly. + Mso::Make(); + }); + } #endif - }; diff --git a/libs/object/tests/swarmTest.cpp b/libs/object/tests/swarmTest.cpp index 7e1e2c6..6f2ba1a 100644 --- a/libs/object/tests/swarmTest.cpp +++ b/libs/object/tests/swarmTest.cpp @@ -12,562 +12,523 @@ Unit tests for classes in the ObjectSwarm.h #include "testAllocators.h" #include -//#define TEST_BAD_INHERITANCE1 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this class. +//#define TEST_BAD_INHERITANCE1 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this +//class. MSO_STRUCT_GUID(ISwarmSample1, "962D2470-7452-43AB-9F74-63545A3E8A58") struct DECLSPEC_NOVTABLE ISwarmSample1 : public IUnknown { - virtual int GetValue1() = 0; + virtual int GetValue1() = 0; }; MSO_STRUCT_GUID(ISwarmSample2, "B7E82DB0-436F-4B05-950F-FC1FE1ACE651") struct DECLSPEC_NOVTABLE ISwarmSample2 : public IUnknown { - virtual int GetValue2() = 0; + virtual int GetValue2() = 0; }; -class SwarmMemberSample1 final - : public Mso::UnknownObject +class SwarmMemberSample1 final : public Mso::UnknownObject { public: - SwarmMemberSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + SwarmMemberSample1(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~SwarmMemberSample1() noexcept - { - m_deleted = true; - } + virtual ~SwarmMemberSample1() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; -class SwarmMemberSample2 final - : public Mso::UnknownObject +class SwarmMemberSample2 final : public Mso::UnknownObject { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - SwarmMemberSample2() noexcept - : m_deleted(nullptr) - , m_other() - { - } + SwarmMemberSample2() noexcept : m_deleted(nullptr), m_other() {} - bool InitializeThis(bool& deleted) noexcept - { - m_deleted = &deleted; - return true; - } + bool InitializeThis(bool& deleted) noexcept + { + m_deleted = &deleted; + return true; + } - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } - Mso::TCntPtr GetOther() noexcept - { - return m_other.Get(); - } + Mso::TCntPtr GetOther() noexcept + { + return m_other.Get(); + } - bool IsDifferentSwarm() const noexcept - { - return m_other.IsDifferentSwarm(); - } + bool IsDifferentSwarm() const noexcept + { + return m_other.IsDifferentSwarm(); + } - void SetOther(SwarmMemberSample1& other) noexcept - { - Mso::TCntPtr swarm = Mso::Swarm::FromObject(this); - VerifyElseCrashSzTag(!swarm.IsEmpty(), "This object must be part of a swarm.", 0x01003708 /* tag_bad2i */); - m_other = Mso::SwarmMemberPtr(&other, *swarm); - } + void SetOther(SwarmMemberSample1& other) noexcept + { + Mso::TCntPtr swarm = Mso::Swarm::FromObject(this); + VerifyElseCrashSzTag(!swarm.IsEmpty(), "This object must be part of a swarm.", 0x01003708 /* tag_bad2i */); + m_other = Mso::SwarmMemberPtr(&other, *swarm); + } protected: - virtual ~SwarmMemberSample2() noexcept - { - *m_deleted = true; - } + virtual ~SwarmMemberSample2() noexcept + { + *m_deleted = true; + } private: - bool* m_deleted; - Mso::SwarmMemberPtr m_other; + bool* m_deleted; + Mso::SwarmMemberPtr m_other; }; -class SwarmMemberSample2Base - : public Mso::UnknownObject +class SwarmMemberSample2Base : public Mso::UnknownObject { public: - SwarmMemberSample2Base(int index, const std::function& onDelete) - : m_index(index) - , m_onDelete(onDelete) - { - } + SwarmMemberSample2Base(int index, const std::function& onDelete) : m_index(index), m_onDelete(onDelete) {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~SwarmMemberSample2Base() noexcept - { - OACR_ASSUME_NOTHROW_BEGIN - m_onDelete(m_index); - OACR_ASSUME_NOTHROW_END - } + virtual ~SwarmMemberSample2Base() noexcept + { + OACR_ASSUME_NOTHROW_BEGIN + m_onDelete(m_index); + OACR_ASSUME_NOTHROW_END + } private: - int m_index; - std::function m_onDelete; + int m_index; + std::function m_onDelete; }; class SwarmMemberSample21 : public SwarmMemberSample2Base { public: - SwarmMemberSample21(int index, const std::function& onDelete) - : SwarmMemberSample2Base(index, onDelete) - { - } + SwarmMemberSample21(int index, const std::function& onDelete) : SwarmMemberSample2Base(index, onDelete) {} }; class SwarmMemberSample22 : public SwarmMemberSample2Base { public: - SwarmMemberSample22(int index, const std::function& onDelete) - : SwarmMemberSample2Base(index, onDelete) - { - } + SwarmMemberSample22(int index, const std::function& onDelete) : SwarmMemberSample2Base(index, onDelete) {} }; -class SwarmMemberSample3CannotAllocate - : public Mso::UnknownObject +class SwarmMemberSample3CannotAllocate : public Mso::UnknownObject { public: - SwarmMemberSample3CannotAllocate() noexcept - { - } + SwarmMemberSample3CannotAllocate() noexcept {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~SwarmMemberSample3CannotAllocate() noexcept - { - } + virtual ~SwarmMemberSample3CannotAllocate() noexcept {} }; -class SwarmMemberSampleBase - : public Mso::UnknownObject +class SwarmMemberSampleBase : public Mso::UnknownObject { public: - SwarmMemberSampleBase() noexcept - { - } + SwarmMemberSampleBase() noexcept {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } protected: - virtual ~SwarmMemberSampleBase() noexcept - { - } + virtual ~SwarmMemberSampleBase() noexcept {} }; -class SwarmMemberSample4Throw - : public SwarmMemberSampleBase +class SwarmMemberSample4Throw : public SwarmMemberSampleBase { public: - using MakePolicy = Mso::MakePolicy::ThrowCtor; + using MakePolicy = Mso::MakePolicy::ThrowCtor; - SwarmMemberSample4Throw() - { - throw std::runtime_error("Test"); - } + SwarmMemberSample4Throw() + { + throw std::runtime_error("Test"); + } }; -class SwarmMemberSample5InitThrow - : public SwarmMemberSampleBase +class SwarmMemberSample5InitThrow : public SwarmMemberSampleBase { public: - using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; + using MakePolicy = Mso::MakePolicy::ThrowCtorAndInitializeThis; - void InitializeThis() - { - UNREFERENCED_OACR(this); - throw std::runtime_error("Test"); - } + void InitializeThis() + { + UNREFERENCED_OACR(this); + throw std::runtime_error("Test"); + } }; #ifdef TEST_BAD_INHERITANCE1 class SomeVirtualClass { public: - virtual ~SomeVirtualClass() noexcept{} + virtual ~SomeVirtualClass() noexcept {} - int x; - int y; + int x; + int y; }; // !!! Mso::UnknownObject must be always the first one in the inheritance !!! class BadSwarmMember1 final - : public SomeVirtualClass - , public Mso::UnknownObject + : public SomeVirtualClass + , public Mso::UnknownObject { public: - virtual int GetValue1() override - { - return 1; - } + virtual int GetValue1() override + { + return 1; + } }; #endif -TEST_CLASS(ObjectSwarmTest) +TEST_CLASS (ObjectSwarmTest) { - TEST_METHOD(ObjectSwarm_OneMember) - { - bool deleted; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted); - TestAssert::IsNotNull(member1.Get()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(ObjectSwarm_OneMember) + { + bool deleted; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted); + TestAssert::IsNotNull(member1.Get()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectSwarm_TwoMembers) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - Mso::TCntPtr member2 = swarm->MakeMember(/*ref*/deleted2); - TestAssert::IsNotNull(member2.Get()); - } - TestAssert::IsTrue(deleted1, L"First Swarm member is not deleted."); - TestAssert::IsTrue(deleted2, L"Second Swarm member is not deleted."); - } + TEST_METHOD(ObjectSwarm_TwoMembers) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + Mso::TCntPtr member2 = swarm->MakeMember(/*ref*/ deleted2); + TestAssert::IsNotNull(member2.Get()); + } + TestAssert::IsTrue(deleted1, L"First Swarm member is not deleted."); + TestAssert::IsTrue(deleted2, L"Second Swarm member is not deleted."); + } - TEST_METHOD(ObjectSwarm_ThreeMembers) - { - // Test that members are deleted in reverse order to how they were created. - const int memberCount = 3; - int deleteOrderIndex = 0; - int deleteOrder[memberCount]; - std::function onDelete = [&deleteOrderIndex, &deleteOrder](int index) noexcept - { - deleteOrder[--deleteOrderIndex] = index; - }; + TEST_METHOD(ObjectSwarm_ThreeMembers) + { + // Test that members are deleted in reverse order to how they were created. + const int memberCount = 3; + int deleteOrderIndex = 0; + int deleteOrder[memberCount]; + std::function onDelete = [&deleteOrderIndex, &deleteOrder](int index) noexcept { + deleteOrder[--deleteOrderIndex] = index; + }; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(deleteOrderIndex++, onDelete); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - Mso::TCntPtr member2 = swarm->MakeMember(deleteOrderIndex++, onDelete); - TestAssert::IsNotNull(member2.Get()); - // Members can be of the same type - Mso::TCntPtr member3 = swarm->MakeMember(deleteOrderIndex++, onDelete); - TestAssert::IsNotNull(member3.Get()); - } + { + Mso::TCntPtr member1 = Mso::Swarm::Make(deleteOrderIndex++, onDelete); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + Mso::TCntPtr member2 = swarm->MakeMember(deleteOrderIndex++, onDelete); + TestAssert::IsNotNull(member2.Get()); + // Members can be of the same type + Mso::TCntPtr member3 = swarm->MakeMember(deleteOrderIndex++, onDelete); + TestAssert::IsNotNull(member3.Get()); + } - TestAssert::AreEqual(0, deleteOrderIndex, L"Not all members are deleted"); + TestAssert::AreEqual(0, deleteOrderIndex, L"Not all members are deleted"); - for (int i = 0; i < memberCount; i++) - { - TestAssert::AreEqual(i, deleteOrder[i], L"Wrong deletion order"); - } - } + for (int i = 0; i < memberCount; i++) + { + TestAssert::AreEqual(i, deleteOrder[i], L"Wrong deletion order"); + } + } - TEST_METHOD(ObjectSwarm_FromObject) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - TestAssert::IsNotNull(swarm.Get()); + TEST_METHOD(ObjectSwarm_FromObject) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + TestAssert::IsNotNull(swarm.Get()); - Mso::TCntPtr member2 = swarm->MakeMember(/*ref*/deleted2); - TestAssert::IsNotNull(member2.Get()); - swarm = Mso::Swarm::FromObject(member2.Get()); - TestAssert::IsNotNull(swarm.Get()); + Mso::TCntPtr member2 = swarm->MakeMember(/*ref*/ deleted2); + TestAssert::IsNotNull(member2.Get()); + swarm = Mso::Swarm::FromObject(member2.Get()); + TestAssert::IsNotNull(swarm.Get()); - Mso::TCntPtr memberIntf1 = qi_cast(member1.Get()); - TestAssert::IsNotNull(memberIntf1.Get()); - swarm = Mso::Swarm::FromObject(memberIntf1.Get()); - TestAssert::IsNotNull(swarm.Get()); + Mso::TCntPtr memberIntf1 = qi_cast(member1.Get()); + TestAssert::IsNotNull(memberIntf1.Get()); + swarm = Mso::Swarm::FromObject(memberIntf1.Get()); + TestAssert::IsNotNull(swarm.Get()); - //Mso::TCntPtr memberIntf2 = qi_cast(member2.Get()); - //TestAssert::IsNotNull(memberIntf2.Get()); - //swarm = Mso::Swarm::FromObject(memberIntf2.Get()); - //TestAssert::IsNotNull(swarm.Get()); - } - TestAssert::IsTrue(deleted1, L"First Swarm member is not deleted."); - TestAssert::IsTrue(deleted2, L"Second Swarm member is not deleted."); - } + // Mso::TCntPtr memberIntf2 = qi_cast(member2.Get()); + // TestAssert::IsNotNull(memberIntf2.Get()); + // swarm = Mso::Swarm::FromObject(memberIntf2.Get()); + // TestAssert::IsNotNull(swarm.Get()); + } + TestAssert::IsTrue(deleted1, L"First Swarm member is not deleted."); + TestAssert::IsTrue(deleted2, L"Second Swarm member is not deleted."); + } - TEST_METHOD(ObjectSwarm_WeakPtr) - { - bool deleted1; - bool deleted2; - { - Mso::WeakPtr memberWeak1; - Mso::WeakPtr memberWeak2; - Mso::WeakPtr memberIntfWeak1; - Mso::WeakPtr memberIntfWeak2; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - Mso::TCntPtr member2 = swarm->MakeMember(/*ref*/deleted2); + TEST_METHOD(ObjectSwarm_WeakPtr) + { + bool deleted1; + bool deleted2; + { + Mso::WeakPtr memberWeak1; + Mso::WeakPtr memberWeak2; + Mso::WeakPtr memberIntfWeak1; + Mso::WeakPtr memberIntfWeak2; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + Mso::TCntPtr member2 = swarm->MakeMember(/*ref*/ deleted2); - memberWeak1 = member1; - memberWeak2 = member2; - memberIntfWeak1 = qi_cast(member1.Get()); - memberIntfWeak2 = qi_cast(member2.Get()); + memberWeak1 = member1; + memberWeak2 = member2; + memberIntfWeak1 = qi_cast(member1.Get()); + memberIntfWeak2 = qi_cast(member2.Get()); - TestAssert::IsFalse(memberWeak1.IsExpired()); - TestAssert::IsFalse(memberWeak2.IsExpired()); - TestAssert::IsFalse(memberIntfWeak1.IsExpired()); - TestAssert::IsFalse(memberIntfWeak2.IsExpired()); + TestAssert::IsFalse(memberWeak1.IsExpired()); + TestAssert::IsFalse(memberWeak2.IsExpired()); + TestAssert::IsFalse(memberIntfWeak1.IsExpired()); + TestAssert::IsFalse(memberIntfWeak2.IsExpired()); - Debug(TestAssert::AreEqual(/*members*/2u + /*weakptr*/4u, member1->GetWeakRef().WeakRefCount())); - Debug(TestAssert::AreEqual(/*members*/2u + /*swarm*/1u, member1->GetWeakRef().RefCount())); + Debug(TestAssert::AreEqual(/*members*/ 2u + /*weakptr*/ 4u, member1->GetWeakRef().WeakRefCount())); + Debug(TestAssert::AreEqual(/*members*/ 2u + /*swarm*/ 1u, member1->GetWeakRef().RefCount())); - Mso::TCntPtr member11 = memberWeak1.GetStrongPtr(); - Mso::TCntPtr member21 = memberWeak2.GetStrongPtr(); - Mso::TCntPtr memberIntf11 = memberIntfWeak1.GetStrongPtr(); - Mso::TCntPtr memberIntf21 = memberIntfWeak2.GetStrongPtr(); - TestAssert::IsNotNull(member11.Get()); - TestAssert::IsNotNull(member21.Get()); - TestAssert::IsNotNull(memberIntf11.Get()); - TestAssert::IsNotNull(memberIntf21.Get()); - } - TestAssert::IsTrue(memberWeak1.IsExpired()); - TestAssert::IsTrue(memberWeak2.IsExpired()); - TestAssert::IsTrue(memberIntfWeak1.IsExpired()); - TestAssert::IsTrue(memberIntfWeak2.IsExpired()); + Mso::TCntPtr member11 = memberWeak1.GetStrongPtr(); + Mso::TCntPtr member21 = memberWeak2.GetStrongPtr(); + Mso::TCntPtr memberIntf11 = memberIntfWeak1.GetStrongPtr(); + Mso::TCntPtr memberIntf21 = memberIntfWeak2.GetStrongPtr(); + TestAssert::IsNotNull(member11.Get()); + TestAssert::IsNotNull(member21.Get()); + TestAssert::IsNotNull(memberIntf11.Get()); + TestAssert::IsNotNull(memberIntf21.Get()); + } + TestAssert::IsTrue(memberWeak1.IsExpired()); + TestAssert::IsTrue(memberWeak2.IsExpired()); + TestAssert::IsTrue(memberIntfWeak1.IsExpired()); + TestAssert::IsTrue(memberIntfWeak2.IsExpired()); - Mso::TCntPtr member11 = memberWeak1.GetStrongPtr(); - Mso::TCntPtr member21 = memberWeak2.GetStrongPtr(); - Mso::TCntPtr memberIntf11 = memberIntfWeak1.GetStrongPtr(); - Mso::TCntPtr memberIntf21 = memberIntfWeak2.GetStrongPtr(); - TestAssert::IsNull(member11.Get()); - TestAssert::IsNull(member21.Get()); - TestAssert::IsNull(memberIntf11.Get()); - TestAssert::IsNull(memberIntf21.Get()); - } - TestAssert::IsTrue(deleted1, L"First Swarm member is not deleted."); - TestAssert::IsTrue(deleted2, L"Second Swarm member is not deleted."); - } + Mso::TCntPtr member11 = memberWeak1.GetStrongPtr(); + Mso::TCntPtr member21 = memberWeak2.GetStrongPtr(); + Mso::TCntPtr memberIntf11 = memberIntfWeak1.GetStrongPtr(); + Mso::TCntPtr memberIntf21 = memberIntfWeak2.GetStrongPtr(); + TestAssert::IsNull(member11.Get()); + TestAssert::IsNull(member21.Get()); + TestAssert::IsNull(memberIntf11.Get()); + TestAssert::IsNull(memberIntf21.Get()); + } + TestAssert::IsTrue(deleted1, L"First Swarm member is not deleted."); + TestAssert::IsTrue(deleted2, L"Second Swarm member is not deleted."); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_SameSwarm) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/deleted2); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member2.Get()); - Mso::TCntPtr member1 = swarm->MakeMember(/*ref*/deleted1); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_SameSwarm) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/ deleted2); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member2.Get()); + Mso::TCntPtr member1 = swarm->MakeMember(/*ref*/ deleted1); - member2->SetOther(*member1); - TestAssert::IsTrue(member1.Get() == member2->GetOther().Get()); - TestAssert::IsFalse(member2->IsDifferentSwarm()); - } - TestAssert::IsTrue(deleted1); - TestAssert::IsTrue(deleted2); - } + member2->SetOther(*member1); + TestAssert::IsTrue(member1.Get() == member2->GetOther().Get()); + TestAssert::IsFalse(member2->IsDifferentSwarm()); + } + TestAssert::IsTrue(deleted1); + TestAssert::IsTrue(deleted2); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_DifferentSwarm) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/deleted2); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_DifferentSwarm) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/ deleted2); - member2->SetOther(*member1); - TestAssert::IsTrue(member1.Get() == member2->GetOther().Get()); - TestAssert::IsTrue(member2->IsDifferentSwarm()); - } - TestAssert::IsTrue(deleted1); - TestAssert::IsTrue(deleted2); - } + member2->SetOther(*member1); + TestAssert::IsTrue(member1.Get() == member2->GetOther().Get()); + TestAssert::IsTrue(member2->IsDifferentSwarm()); + } + TestAssert::IsTrue(deleted1); + TestAssert::IsTrue(deleted2); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_KnownSameSwarm) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member0 = Mso::Swarm::Make(/*ref*/deleted2); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member0.Get()); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_KnownSameSwarm) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member0 = Mso::Swarm::Make(/*ref*/ deleted2); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member0.Get()); - Mso::SwarmMemberPtr member1 = - swarm->MakeMember(/*ref*/deleted1); - TestAssert::IsNotNull(member1.Get()); + Mso::SwarmMemberPtr member1 = + swarm->MakeMember(/*ref*/ deleted1); + TestAssert::IsNotNull(member1.Get()); - Mso::SwarmMemberPtr member2 = std::move(member1); - TestAssert::IsNull(member1.Get()); - TestAssert::IsNotNull(member2.Get()); + Mso::SwarmMemberPtr member2 = std::move(member1); + TestAssert::IsNull(member1.Get()); + TestAssert::IsNotNull(member2.Get()); - using std::swap; - swap(member1, member2); - TestAssert::IsNotNull(member1.Get()); - TestAssert::IsNull(member2.Get()); - TestAssert::IsFalse(member1.IsEmpty()); - TestAssert::IsTrue(member2.IsEmpty()); - } - TestAssert::IsTrue(deleted1); - TestAssert::IsTrue(deleted2); - } + using std::swap; + swap(member1, member2); + TestAssert::IsNotNull(member1.Get()); + TestAssert::IsNull(member2.Get()); + TestAssert::IsFalse(member1.IsEmpty()); + TestAssert::IsTrue(member2.IsEmpty()); + } + TestAssert::IsTrue(deleted1); + TestAssert::IsTrue(deleted2); + } - TEST_METHOD(ObjectSwarm_MakeMember_CannotAllocate) - { - bool deleted1; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + TEST_METHOD(ObjectSwarm_MakeMember_CannotAllocate) + { + bool deleted1; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - TestAssert::ExpectVEC([&]() - { - swarm->MakeMember(); - }); + TestAssert::ExpectVEC([&]() { swarm->MakeMember(); }); - Debug(TestAssert::AreEqual(2u, swarm->RefCount())); - Debug(TestAssert::AreEqual(1u, swarm->WeakRefCount())); - } - TestAssert::IsTrue(deleted1); - } + Debug(TestAssert::AreEqual(2u, swarm->RefCount())); + Debug(TestAssert::AreEqual(1u, swarm->WeakRefCount())); + } + TestAssert::IsTrue(deleted1); + } - TEST_METHOD(ObjectSwarm_MakeMember_ConstructorThrows) - { - bool deleted1; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + TEST_METHOD(ObjectSwarm_MakeMember_ConstructorThrows) + { + bool deleted1; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - TestAssert::ExpectException([&]() - { - swarm->MakeMember(); - }); + TestAssert::ExpectException([&]() { swarm->MakeMember(); }); - Debug(TestAssert::AreEqual(2u, swarm->RefCount())); - Debug(TestAssert::AreEqual(1u, swarm->WeakRefCount())); - } - TestAssert::IsTrue(deleted1); - } + Debug(TestAssert::AreEqual(2u, swarm->RefCount())); + Debug(TestAssert::AreEqual(1u, swarm->WeakRefCount())); + } + TestAssert::IsTrue(deleted1); + } - TEST_METHOD(ObjectSwarm_MakeMember_InitializeThrows) - { - bool deleted1; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); + TEST_METHOD(ObjectSwarm_MakeMember_InitializeThrows) + { + bool deleted1; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member1.Get()); - TestAssert::ExpectException([&]() - { - swarm->MakeMember(); - }); + TestAssert::ExpectException([&]() { swarm->MakeMember(); }); - Debug(TestAssert::AreEqual(2u, swarm->RefCount())); - Debug(TestAssert::AreEqual(1u, swarm->WeakRefCount())); - } - TestAssert::IsTrue(deleted1); - } + Debug(TestAssert::AreEqual(2u, swarm->RefCount())); + Debug(TestAssert::AreEqual(1u, swarm->WeakRefCount())); + } + TestAssert::IsTrue(deleted1); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_ObjectWeakRef_SameSwarm) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/deleted2); - Mso::TCntPtr swarm = Mso::Swarm::FromObject(member2.Get()); - Mso::TCntPtr weakRef2 = &member2->GetWeakRef(); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_ObjectWeakRef_SameSwarm) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/ deleted2); + Mso::TCntPtr swarm = Mso::Swarm::FromObject(member2.Get()); + Mso::TCntPtr weakRef2 = &member2->GetWeakRef(); - Mso::TCntPtr member1 = swarm->MakeMember(/*ref*/deleted1); + Mso::TCntPtr member1 = swarm->MakeMember(/*ref*/ deleted1); - Mso::SwarmMemberPtr swarmPtr = Mso::SwarmMemberPtr(member1.Get(), *weakRef2); - TestAssert::IsTrue(swarmPtr.Get() == member1.Get()); - TestAssert::IsFalse(swarmPtr.IsDifferentSwarm()); - } - TestAssert::IsTrue(deleted1); - TestAssert::IsTrue(deleted2); - } + Mso::SwarmMemberPtr swarmPtr = + Mso::SwarmMemberPtr(member1.Get(), *weakRef2); + TestAssert::IsTrue(swarmPtr.Get() == member1.Get()); + TestAssert::IsFalse(swarmPtr.IsDifferentSwarm()); + } + TestAssert::IsTrue(deleted1); + TestAssert::IsTrue(deleted2); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_ObjectWeakRef_DifferentSwarm) - { - bool deleted1; - bool deleted2; - { - Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/deleted1); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_ObjectWeakRef_DifferentSwarm) + { + bool deleted1; + bool deleted2; + { + Mso::TCntPtr member1 = Mso::Swarm::Make(/*ref*/ deleted1); - Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/deleted2); - Mso::TCntPtr weakRef2 = &member2->GetWeakRef(); + Mso::TCntPtr member2 = Mso::Swarm::Make(/*ref*/ deleted2); + Mso::TCntPtr weakRef2 = &member2->GetWeakRef(); - Mso::SwarmMemberPtr swarmPtr = Mso::SwarmMemberPtr(member1.Get(), *weakRef2); - TestAssert::IsTrue(swarmPtr.Get() == member1.Get()); - TestAssert::IsTrue(swarmPtr.IsDifferentSwarm()); - } - TestAssert::IsTrue(deleted1); - TestAssert::IsTrue(deleted2); - } + Mso::SwarmMemberPtr swarmPtr = + Mso::SwarmMemberPtr(member1.Get(), *weakRef2); + TestAssert::IsTrue(swarmPtr.Get() == member1.Get()); + TestAssert::IsTrue(swarmPtr.IsDifferentSwarm()); + } + TestAssert::IsTrue(deleted1); + TestAssert::IsTrue(deleted2); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_EqualityToNull) - { - bool deleted = false; - { - Mso::TCntPtr member = Mso::Swarm::Make(/*ref*/deleted); - Mso::SwarmMemberPtr swarmPtr = Mso::SwarmMemberPtr(member.Get(), *Mso::Swarm::FromObject(member.Get())); - TestAssert::IsFalse(swarmPtr.IsDifferentSwarm()); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_EqualityToNull) + { + bool deleted = false; + { + Mso::TCntPtr member = Mso::Swarm::Make(/*ref*/ deleted); + Mso::SwarmMemberPtr swarmPtr = + Mso::SwarmMemberPtr(member.Get(), *Mso::Swarm::FromObject(member.Get())); + TestAssert::IsFalse(swarmPtr.IsDifferentSwarm()); - TestAssert::IsTrue(swarmPtr != nullptr); - TestAssert::IsTrue(nullptr != swarmPtr); + TestAssert::IsTrue(swarmPtr != nullptr); + TestAssert::IsTrue(nullptr != swarmPtr); - swarmPtr.Reset(); + swarmPtr.Reset(); - TestAssert::IsTrue(swarmPtr == nullptr); - TestAssert::IsTrue(nullptr == swarmPtr); - } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(swarmPtr == nullptr); + TestAssert::IsTrue(nullptr == swarmPtr); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(ObjectSwarm_SwarmMemberPtr_KnownSameSwarm_EqualityToNull) - { - bool deleted = false; - { - Mso::TCntPtr member = Mso::Swarm::Make(/*ref*/deleted); - Mso::SwarmMemberPtr swarmPtr = Mso::SwarmMemberPtr(member.Get()); - TestAssert::IsFalse(swarmPtr.IsDifferentSwarm()); + TEST_METHOD(ObjectSwarm_SwarmMemberPtr_KnownSameSwarm_EqualityToNull) + { + bool deleted = false; + { + Mso::TCntPtr member = Mso::Swarm::Make(/*ref*/ deleted); + Mso::SwarmMemberPtr swarmPtr = + Mso::SwarmMemberPtr(member.Get()); + TestAssert::IsFalse(swarmPtr.IsDifferentSwarm()); - TestAssert::IsTrue(swarmPtr != nullptr); - TestAssert::IsTrue(nullptr != swarmPtr); + TestAssert::IsTrue(swarmPtr != nullptr); + TestAssert::IsTrue(nullptr != swarmPtr); - swarmPtr.Reset(); + swarmPtr.Reset(); - TestAssert::IsTrue(swarmPtr == nullptr); - TestAssert::IsTrue(nullptr == swarmPtr); - } - TestAssert::IsTrue(deleted); - } + TestAssert::IsTrue(swarmPtr == nullptr); + TestAssert::IsTrue(nullptr == swarmPtr); + } + TestAssert::IsTrue(deleted); + } #if defined(DEBUG) && defined(TEST_BAD_INHERITANCE1) - TESTMETHOD_REQUIRES_SEH(ObjectFixedSwarm_BadInheritance1) - { - TestAssert::ExpectVEC([&]() noexcept - { - // You will see a memory leak here because we cannot destroy object correctly. - Mso::Swarm::Make(); - }); - } + TESTMETHOD_REQUIRES_SEH(ObjectFixedSwarm_BadInheritance1) + { + TestAssert::ExpectVEC([&]() noexcept { + // You will see a memory leak here because we cannot destroy object correctly. + Mso::Swarm::Make(); + }); + } #endif - }; diff --git a/libs/object/tests/testAllocators.h b/libs/object/tests/testAllocators.h index d381968..5421ae5 100644 --- a/libs/object/tests/testAllocators.h +++ b/libs/object/tests/testAllocators.h @@ -14,96 +14,87 @@ // Special test allocator that cannot allocate memory and returns nullptr. struct BadMakeAllocator { - static void* Allocate(size_t /*size*/) noexcept - { - return nullptr; - } + static void* Allocate(size_t /*size*/) noexcept + { + return nullptr; + } - static void Deallocate(void* /*buffer*/) noexcept - { - } + static void Deallocate(void* /*buffer*/) noexcept {} }; using BadAllocSimpleRefCount = Mso::SimpleRefCountPolicy; using BadAllocWeakRefCount = Mso::WeakRefCountPolicy; - //============================================================================= // StatefulMakeAllocator helps testing stateful allocators //============================================================================= struct IMyMemHeap { - virtual void* Alloc(size_t size) noexcept = 0; - virtual void Free(void* ptr) noexcept = 0; + virtual void* Alloc(size_t size) noexcept = 0; + virtual void Free(void* ptr) noexcept = 0; }; struct MyMemHeap : public IMyMemHeap { - MyMemHeap(bool& allocCalled, bool& freeCalled) noexcept - : m_allocCalled(allocCalled) - , m_freeCalled(freeCalled) - { - } + MyMemHeap(bool& allocCalled, bool& freeCalled) noexcept : m_allocCalled(allocCalled), m_freeCalled(freeCalled) {} - DECLARE_COPYCONSTR_AND_ASSIGNMENT(MyMemHeap); - - virtual void* Alloc(size_t size) noexcept override - { - m_allocCalled = true; - return Mso::Memory::AllocateEx(size, Mso::Memory::AllocFlags::ShutdownLeak); - } + DECLARE_COPYCONSTR_AND_ASSIGNMENT(MyMemHeap); - virtual void Free(void* ptr) noexcept override - { - m_freeCalled = true; - Mso::Memory::Free(ptr); - } + virtual void* Alloc(size_t size) noexcept override + { + m_allocCalled = true; + return Mso::Memory::AllocateEx(size, Mso::Memory::AllocFlags::ShutdownLeak); + } + + virtual void Free(void* ptr) noexcept override + { + m_freeCalled = true; + Mso::Memory::Free(ptr); + } private: - bool& m_allocCalled; - bool& m_freeCalled; + bool& m_allocCalled; + bool& m_freeCalled; }; struct StatefulMakeAllocator { - static const size_t HeaderSize = 8; // To make sure that we can store a pointer and to have 8 byte alignment for object. + static const size_t HeaderSize = + 8; // To make sure that we can store a pointer and to have 8 byte alignment for object. - static void* Allocate(size_t size, IMyMemHeap* memHeap) noexcept - { - size_t bufferSize = size + HeaderSize; - void* buffer = memHeap->Alloc(bufferSize); - *reinterpret_cast(buffer) = memHeap; - return static_cast(buffer) + HeaderSize; - } + static void* Allocate(size_t size, IMyMemHeap* memHeap) noexcept + { + size_t bufferSize = size + HeaderSize; + void* buffer = memHeap->Alloc(bufferSize); + *reinterpret_cast(buffer) = memHeap; + return static_cast(buffer) + HeaderSize; + } - static void Deallocate(void* ptr) noexcept - { - void* buffer = static_cast(ptr) - HeaderSize; - IMyMemHeap* memHeap = *reinterpret_cast(buffer); - memHeap->Free(buffer); - } + static void Deallocate(void* ptr) noexcept + { + void* buffer = static_cast(ptr) - HeaderSize; + IMyMemHeap* memHeap = *reinterpret_cast(buffer); + memHeap->Free(buffer); + } }; using StatefulAllocSimpleRefCount = Mso::SimpleRefCountPolicy; using StatefulAllocWeakRefCount = Mso::WeakRefCountPolicy; - //============================================================================= -// BadStatefulAllocator helps testing stateful allocators that may return +// BadStatefulAllocator helps testing stateful allocators that may return // null from Allocate method. //============================================================================= struct BadStatefulAllocator { - static void* Allocate(size_t /*size*/, IMyMemHeap* /*memHeap*/) noexcept - { - return nullptr; - } + static void* Allocate(size_t /*size*/, IMyMemHeap* /*memHeap*/) noexcept + { + return nullptr; + } - static void Deallocate(void* /*ptr*/) noexcept - { - } + static void Deallocate(void* /*ptr*/) noexcept {} }; using BadStatefulAllocSimpleRefCount = Mso::SimpleRefCountPolicy; diff --git a/libs/object/tests/unknownObjectTest.cpp b/libs/object/tests/unknownObjectTest.cpp index 3b0d2bb..5ea0465 100644 --- a/libs/object/tests/unknownObjectTest.cpp +++ b/libs/object/tests/unknownObjectTest.cpp @@ -16,24 +16,25 @@ Unit tests for classes in the msoUnknownObject.h #include //#define TEST_BAD_INHERITANCE1 // Uncomment to see compilation error -//#define TEST_BAD_INHERITANCE2 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this class. +//#define TEST_BAD_INHERITANCE2 // Uncomment to confirm VEC, but observe a memory leak. We cannot safely destroy this +//class. MSO_STRUCT_GUID(IBaseSample1, "16872411-FA64-436C-92F4-22FE6B536FC8") struct DECLSPEC_NOVTABLE IBaseSample1 : public IUnknown { - virtual int GetValue1() const = 0; + virtual int GetValue1() const = 0; }; MSO_STRUCT_GUID(IBaseSample2, "978F3765-88B4-4610-A607-16FFD5537E9B") struct DECLSPEC_NOVTABLE IBaseSample2 : public IUnknown { - virtual int GetValue2() const = 0; + virtual int GetValue2() const = 0; }; MSO_STRUCT_GUID(IBaseSample3, "DB0CE125-7AF8-47F5-A8F9-D176619ABA76") struct DECLSPEC_NOVTABLE IBaseSample3 : public IUnknown { - virtual int GetValue3() const = 0; + virtual int GetValue3() const = 0; }; // Next four interfaces are interfaces for the case when we have only QueryInterface without AddRef/Release @@ -41,2124 +42,1962 @@ struct DECLSPEC_NOVTABLE IBaseSample3 : public IUnknown MSO_STRUCT_GUID(ISimpleUnknownSample1, "F770BE39-7ED8-4A8E-84FD-B5441CD7525E") struct DECLSPEC_NOVTABLE ISimpleUnknownSample1 { - virtual HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) = 0; - virtual int GetValue1() const = 0; + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) = 0; + virtual int GetValue1() const = 0; }; MSO_STRUCT_GUID(ISimpleUnknownSample2, "47D5B036-BF11-4AF7-8D31-EB646E8D8CF2") struct DECLSPEC_NOVTABLE ISimpleUnknownSample2 { - virtual HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) = 0; - virtual int GetValue2() const = 0; + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) = 0; + virtual int GetValue2() const = 0; }; MSO_STRUCT_GUID(ISimpleUnknownSample21, "ABB7D11B-D496-42CA-9529-DFB20226435E") struct DECLSPEC_NOVTABLE ISimpleUnknownSample21 : public ISimpleUnknownSample2 { - virtual int GetValue21() const = 0; + virtual int GetValue21() const = 0; }; MSO_STRUCT_GUID(ISimpleUnknownSample3, "47BF0755-FA82-4D76-B609-520195A1F03E") struct DECLSPEC_NOVTABLE ISimpleUnknownSample3 { - virtual HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) = 0; - virtual int GetValue3() const = 0; + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) = 0; + virtual int GetValue3() const = 0; }; // Unknown object with simple ref count that implements one IUnknown based interface. -class UnknownSample1 final - : public Mso::UnknownObject +class UnknownSample1 final : public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } protected: - virtual ~UnknownSample1() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample1() noexcept + { + m_deleted = true; + } private: - UnknownSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample1(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; -class UnknownSample11 final - : public Mso::UnknownObject +class UnknownSample11 final : public Mso::UnknownObject { public: - using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; - friend MakePolicy; // To allow constructor to be private or protected. + using MakePolicy = Mso::MakePolicy::NoThrowCtorAndInitializeThis; + friend MakePolicy; // To allow constructor to be private or protected. - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } protected: - virtual ~UnknownSample11() noexcept - { - *m_deleted = true; - } + virtual ~UnknownSample11() noexcept + { + *m_deleted = true; + } private: - UnknownSample11() noexcept - { - } + UnknownSample11() noexcept {} - bool InitializeThis(bool& deleted) noexcept - { - m_deleted = &deleted; - return true; - } + bool InitializeThis(bool& deleted) noexcept + { + m_deleted = &deleted; + return true; + } private: - bool* m_deleted = nullptr; + bool* m_deleted = nullptr; }; // Unknown object with simple ref count that implements two IUnknown based interfaces. -class UnknownSample2 final - : public Mso::UnknownObject +class UnknownSample2 final : public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } protected: - virtual ~UnknownSample2() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample2() noexcept + { + m_deleted = true; + } private: - UnknownSample2(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample2(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; -class UnknownSample21 final - : public Mso::UnknownObject +class UnknownSample21 final : public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } private: - UnknownSample21() = default; + UnknownSample21() = default; }; // Unknown object with simple ref count that implements two IUnknown based interfaces. // Added QI support for the class itself. MSO_CLASS_GUID(UnknownSample3, "5AF68CBD-A9D3-4B00-85F5-A0F8DA6E51DF") class UnknownSample3 final - : public Mso::UnknownObject, IBaseSample1, IBaseSample2> + : public Mso::UnknownObject, IBaseSample1, IBaseSample2> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } protected: - virtual ~UnknownSample3() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample3() noexcept + { + m_deleted = true; + } private: - UnknownSample3(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample3(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Unknown object with support for weak references that implements one IUnknown based interface. -class UnknownSample4 final - : public Mso::UnknownObject +class UnknownSample4 final : public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } protected: - virtual ~UnknownSample4() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample4() noexcept + { + m_deleted = true; + } private: - UnknownSample4(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample4(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Unknown object with support for weak references that implements two IUnknown based interfaces. -class UnknownSample5 final - : public Mso::UnknownObject +class UnknownSample5 final : public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } protected: - virtual ~UnknownSample5() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample5() noexcept + { + m_deleted = true; + } private: - UnknownSample5(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample5(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Unknown object with support for weak references that implements two IUnknown based interfaces. // Added QI support for the class itself. MSO_CLASS_GUID(UnknownSample6, "96075AC6-AE32-4ADF-AE8F-8B6B62790530") class UnknownSample6 final - : public Mso::UnknownObject, IBaseSample1, IBaseSample2> + : public Mso::UnknownObject< + Mso::RefCountStrategy::WeakRef, + Mso::QueryCastDerived, + IBaseSample1, + IBaseSample2> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } private: - UnknownSample6(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample6(bool& deleted) noexcept : m_deleted(deleted) {} protected: - virtual ~UnknownSample6() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample6() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; // Types below are for a demo how to query for a base interface if querying for it is not implemented in a base class. MSO_STRUCT_GUID(IDerivedBase1, "34C53457-1760-44BE-BC4B-39EC92E94DDC") struct DECLSPEC_NOVTABLE IDerivedBase1 : IBaseSample1 { - virtual int GetValue11() const = 0; + virtual int GetValue11() const = 0; }; class IMockDerivedBase : public Mso::QueryCastList { - virtual int GetValue1() const override - { - return 1; - } + virtual int GetValue1() const override + { + return 1; + } - virtual int GetValue11() const override - { - return 11; - } + virtual int GetValue11() const override + { + return 11; + } }; // To demo how to query for a base interface if querying for it is not implemented in a base class. // Here we want to query for IBaseSample1, and IMockDerivedBase does not implement QueryCast for it. // QueryCastChain only inherits from the first template parameter type and implements QueryCast for all provided types. class UnknownSample7 final - : public Mso::UnknownObject, IBaseSample2> + : public Mso::UnknownObject, IBaseSample2> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } protected: - virtual ~UnknownSample7() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample7() noexcept + { + m_deleted = true; + } private: - UnknownSample7(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample7(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; -class UnknownSample8 final - : public Mso::UnknownObject +class UnknownSample8 final : public Mso::UnknownObject { public: - UnknownSample8(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample8(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual ~UnknownSample8() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample8() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; /// Base class for UnknownObject that implements two interfaces and has non-default constructors. -class UnknownSample9Base - : public Mso::QueryCastList +class UnknownSample9Base : public Mso::QueryCastList { public: - virtual int GetValue1() const noexcept override - { - return m_param0 + m_param1 + m_param2; - } + virtual int GetValue1() const noexcept override + { + return m_param0 + m_param1 + m_param2; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } protected: - UnknownSample9Base() = default; - UnknownSample9Base(int param0) noexcept : m_param0(param0) {} - UnknownSample9Base(int param0, int param1) noexcept : m_param0(param0), m_param1(param1) {} - UnknownSample9Base(int param0, int param1, int param2) noexcept : m_param0(param0), m_param1(param1), m_param2(param2) {} + UnknownSample9Base() = default; + UnknownSample9Base(int param0) noexcept : m_param0(param0) {} + UnknownSample9Base(int param0, int param1) noexcept : m_param0(param0), m_param1(param1) {} + UnknownSample9Base(int param0, int param1, int param2) noexcept : m_param0(param0), m_param1(param1), m_param2(param2) + { + } private: - int m_param0 = 0; - int m_param1 = 0; - int m_param2 = 0; + int m_param0 = 0; + int m_param1 = 0; + int m_param2 = 0; }; /// Simple ref counted object inherited from UnknownSample9Base with non-default constructors. -class UnknownSample91 final - : public Mso::UnknownObject +class UnknownSample91 final : public Mso::UnknownObject { - using Super = UnknownObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = UnknownObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } protected: - virtual ~UnknownSample91() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample91() noexcept + { + m_deleted = true; + } private: - UnknownSample91(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample91(bool& deleted) noexcept : m_deleted(deleted) {} - UnknownSample91(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + UnknownSample91(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - UnknownSample91(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + UnknownSample91(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - UnknownSample91(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + UnknownSample91(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } private: - bool& m_deleted; + bool& m_deleted; }; /// Object with a weak reference inherited from UnknownSample9Base with non-default constructors. class UnknownSample92 final - : public Mso::UnknownObject + : public Mso::UnknownObject { - using Super = UnknownObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = UnknownObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } protected: - virtual ~UnknownSample92() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample92() noexcept + { + m_deleted = true; + } private: - UnknownSample92(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample92(bool& deleted) noexcept : m_deleted(deleted) {} - UnknownSample92(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + UnknownSample92(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - UnknownSample92(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + UnknownSample92(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - UnknownSample92(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + UnknownSample92(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } private: - bool& m_deleted; + bool& m_deleted; }; /// Object without reference counting and inherited from UnknownSample9Base with non-default constructors. class UnknownSample93 final - : public Mso::UnknownObject + : public Mso::UnknownObject { - using Super = UnknownObjectType; + using Super = UnknownObjectType; public: - UnknownSample93(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample93(bool& deleted) noexcept : m_deleted(deleted) {} - UnknownSample93(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + UnknownSample93(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - UnknownSample93(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + UnknownSample93(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - UnknownSample93(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + UnknownSample93(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } - virtual ~UnknownSample93() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample93() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; // Object with no reference and no query counting and inherited from UnknownSample9Base with non-default constructors. class UnknownSample94 final - : public Mso::UnknownObject + : public Mso::UnknownObject { - using Super = UnknownObjectType; + using Super = UnknownObjectType; public: - UnknownSample94(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample94(bool& deleted) noexcept : m_deleted(deleted) {} - UnknownSample94(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + UnknownSample94(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - UnknownSample94(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + UnknownSample94(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - UnknownSample94(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + UnknownSample94(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } - virtual ~UnknownSample94() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample94() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; struct AsyncDeleter2 { - template - static void Delete(TObject* obj) noexcept - { - // Destroy object asynchronously - obj->SetAsyncDestroy(); - try - { - // Ideally we want to show here how to use dispatch queues, but we cannot add DispatchQueue liblet dependency here. - std::thread([obj]() noexcept { TObject::RefCountPolicy::template Delete(obj); }).detach(); - } - catch (...) - { - VerifyElseCrashTag(false, 0x01003709 /* tag_bad2j */); - } - } + template + static void Delete(TObject* obj) noexcept + { + // Destroy object asynchronously + obj->SetAsyncDestroy(); + try + { + // Ideally we want to show here how to use dispatch queues, but we cannot add DispatchQueue liblet dependency + // here. + std::thread([obj]() noexcept { TObject::RefCountPolicy::template Delete(obj); }).detach(); + } + catch (...) + { + VerifyElseCrashTag(false, 0x01003709 /* tag_bad2j */); + } + } }; MSO_STRUCT_GUID(ITestAsyncDestroy2, "40d32222-f341-4d44-beae-cf6e2fe7fca9") struct ITestAsyncDestroy2 { - virtual void SetAsyncDestroy() noexcept = 0; + virtual void SetAsyncDestroy() noexcept = 0; }; // To test custom deleter class UnknownSample101 final - : public Mso::UnknownObject, IBaseSample1, ITestAsyncDestroy2> + : public Mso::UnknownObject, IBaseSample1, ITestAsyncDestroy2> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual void SetAsyncDestroy() noexcept override - { - m_isAsyncDestroy = true; - } + virtual void SetAsyncDestroy() noexcept override + { + m_isAsyncDestroy = true; + } protected: - virtual ~UnknownSample101() noexcept override - { - m_deleted.Set(); - } + virtual ~UnknownSample101() noexcept override + { + m_deleted.Set(); + } private: - UnknownSample101(Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept - : m_deleted(deleted) - , m_isAsyncDestroy(isAsyncDestroy) - { - } + UnknownSample101(Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept + : m_deleted(deleted), m_isAsyncDestroy(isAsyncDestroy) + { + } private: - Mso::Async::ManualResetEvent& m_deleted; - bool& m_isAsyncDestroy; + Mso::Async::ManualResetEvent& m_deleted; + bool& m_isAsyncDestroy; }; // To test custom deleter class UnknownSample102 final - : public Mso::UnknownObject, IBaseSample1, ITestAsyncDestroy2> + : public Mso::UnknownObject, IBaseSample1, ITestAsyncDestroy2> { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual void SetAsyncDestroy() noexcept override - { - m_isAsyncDestroy = true; - } + virtual void SetAsyncDestroy() noexcept override + { + m_isAsyncDestroy = true; + } protected: - virtual ~UnknownSample102() noexcept - { - m_deleted.Set(); - } + virtual ~UnknownSample102() noexcept + { + m_deleted.Set(); + } private: - UnknownSample102(Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept - : m_deleted(deleted) - , m_isAsyncDestroy(isAsyncDestroy) - { - } + UnknownSample102(Mso::Async::ManualResetEvent& deleted, bool& isAsyncDestroy) noexcept + : m_deleted(deleted), m_isAsyncDestroy(isAsyncDestroy) + { + } private: - Mso::Async::ManualResetEvent& m_deleted; - bool& m_isAsyncDestroy; + Mso::Async::ManualResetEvent& m_deleted; + bool& m_isAsyncDestroy; }; // Object has a custom QueryInterface where it sets *ppvObject to nullptr in the beginning. -class UnknownSample111 final - : public Mso::UnknownObject +class UnknownSample111 final : public Mso::UnknownObject { - using Super = UnknownObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = UnknownObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - _Success_(return == S_OK) - STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override - { - *ppvObject = nullptr; // This is not needed but some code in Office does it. - return Super::QueryInterface(riid, ppvObject); - } + _Success_(return == S_OK) STDMETHOD(QueryInterface)(const GUID& riid, _Outptr_ void** ppvObject) noexcept override + { + *ppvObject = nullptr; // This is not needed but some code in Office does it. + return Super::QueryInterface(riid, ppvObject); + } - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } private: - UnknownSample111() = default; + UnknownSample111() = default; }; // Simple ref counted object inherited from IBaseSample1 with no refcounting and no query. -class UnknownSample12 final - : public Mso::UnknownObject +class UnknownSample12 final : public Mso::UnknownObject { public: - UnknownSample12(bool& deleted) noexcept - : m_deleted(deleted) - { - } + UnknownSample12(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual ~UnknownSample12() noexcept - { - m_deleted = true; - } + virtual ~UnknownSample12() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; // Agile object that implements a free threaded marshaller, and implements a simple ref counting. -class AgileSample1 final - : public Mso::AgileUnknownObject +class AgileSample1 final : public Mso::AgileUnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } protected: - virtual ~AgileSample1() noexcept - { - m_deleted = true; - } + virtual ~AgileSample1() noexcept + { + m_deleted = true; + } private: - AgileSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + AgileSample1(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Agile object that implements a free threaded marshaller, and supports weak references. -class AgileSample2 final - : public Mso::AgileUnknownObject +class AgileSample2 final : public Mso::AgileUnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } protected: - virtual ~AgileSample2() noexcept - { - m_deleted = true; - } + virtual ~AgileSample2() noexcept + { + m_deleted = true; + } private: - AgileSample2(bool& deleted) noexcept - : m_deleted(deleted) - { - } + AgileSample2(bool& deleted) noexcept : m_deleted(deleted) {} private: - bool& m_deleted; + bool& m_deleted; }; // Agile object that implements a free threaded marshaller, and does not implement ref counting. -class AgileSample3 final - : public Mso::AgileUnknownObject +class AgileSample3 final : public Mso::AgileUnknownObject { public: - AgileSample3(bool& deleted) noexcept - : m_deleted(deleted) - { - } + AgileSample3(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual ~AgileSample3() noexcept - { - m_deleted = true; - } + virtual ~AgileSample3() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; /// Simple ref counted agile object inherited from UnknownSample9Base with non-default constructors. -class AgileSample41 final - : public Mso::AgileUnknownObject +class AgileSample41 final : public Mso::AgileUnknownObject { - using Super = AgileUnknownObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = AgileUnknownObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } protected: - virtual ~AgileSample41() noexcept - { - m_deleted = true; - } + virtual ~AgileSample41() noexcept + { + m_deleted = true; + } private: - AgileSample41(bool& deleted) noexcept - : m_deleted(deleted) - { - } + AgileSample41(bool& deleted) noexcept : m_deleted(deleted) {} - AgileSample41(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + AgileSample41(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - AgileSample41(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } - - AgileSample41(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + AgileSample41(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} + AgileSample41(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } private: - bool& m_deleted; + bool& m_deleted; }; /// Agile object with a weak reference inherited from UnknownSample9Base with non-default constructors. class AgileSample42 final - : public Mso::AgileUnknownObject + : public Mso::AgileUnknownObject { - using Super = AgileUnknownObjectType; - friend MakePolicy; // To allow constructor to be private or protected. + using Super = AgileUnknownObjectType; + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } protected: - virtual ~AgileSample42() noexcept - { - m_deleted = true; - } + virtual ~AgileSample42() noexcept + { + m_deleted = true; + } private: - AgileSample42(bool& deleted) noexcept - : m_deleted(deleted) - { - } + AgileSample42(bool& deleted) noexcept : m_deleted(deleted) {} - AgileSample42(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + AgileSample42(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - AgileSample42(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + AgileSample42(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - AgileSample42(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + AgileSample42(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } private: - bool& m_deleted; + bool& m_deleted; }; /// Agile object without reference counting and inherited from UnknownSample9Base with non-default constructors. class AgileSample43 final - : public Mso::AgileUnknownObject + : public Mso::AgileUnknownObject { - using Super = AgileUnknownObjectType; + using Super = AgileUnknownObjectType; public: - AgileSample43(bool& deleted) noexcept - : m_deleted(deleted) - { - } + AgileSample43(bool& deleted) noexcept : m_deleted(deleted) {} - AgileSample43(bool& deleted, int param0) noexcept - : Super(param0) - , m_deleted(deleted) - { - } + AgileSample43(bool& deleted, int param0) noexcept : Super(param0), m_deleted(deleted) {} - AgileSample43(bool& deleted, int param0, int param1) noexcept - : Super(param0, param1) - , m_deleted(deleted) - { - } + AgileSample43(bool& deleted, int param0, int param1) noexcept : Super(param0, param1), m_deleted(deleted) {} - AgileSample43(bool& deleted, int param0, int param1, int param2) noexcept - : Super(param0, param1, param2) - , m_deleted(deleted) - { - } + AgileSample43(bool& deleted, int param0, int param1, int param2) noexcept + : Super(param0, param1, param2), m_deleted(deleted) + { + } - virtual int GetValue3() const noexcept override - { - return 1; - } + virtual int GetValue3() const noexcept override + { + return 1; + } - virtual ~AgileSample43() noexcept - { - m_deleted = true; - } + virtual ~AgileSample43() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; -class SimpleUnknownSample1 final - : public Mso::UnknownObject +class SimpleUnknownSample1 final : public Mso::UnknownObject { public: - SimpleUnknownSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + SimpleUnknownSample1(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual ~SimpleUnknownSample1() noexcept - { - m_deleted = true; - } + virtual ~SimpleUnknownSample1() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; class SimpleUnknownSample2 final - : public Mso::UnknownObject + : public Mso::UnknownObject { public: - SimpleUnknownSample2(bool& deleted) noexcept - : m_deleted(deleted) - { - } + SimpleUnknownSample2(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } - virtual ~SimpleUnknownSample2() noexcept - { - m_deleted = true; - } + virtual ~SimpleUnknownSample2() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; class SimpleUnknownSample3 final - : public Mso::UnknownObject> + : public Mso::UnknownObject< + Mso::RefCountStrategy::NoRefCount, + ISimpleUnknownSample1, + Mso::QueryCastChain> { public: - SimpleUnknownSample3(bool& deleted) noexcept - : m_deleted(deleted) - { - } + SimpleUnknownSample3(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } - virtual int GetValue2() const noexcept override - { - return 2; - } + virtual int GetValue2() const noexcept override + { + return 2; + } - virtual int GetValue21() const noexcept override - { - return 21; - } + virtual int GetValue21() const noexcept override + { + return 21; + } - virtual ~SimpleUnknownSample3() noexcept - { - m_deleted = true; - } + virtual ~SimpleUnknownSample3() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; class SomeVirtualClass { public: - virtual ~SomeVirtualClass() = default; + virtual ~SomeVirtualClass() = default; - int x; - int y; + int x; + int y; }; #ifdef TEST_BAD_INHERITANCE1 // !!! Mso::UnknownObject must be always the first one in the inheritance !!! class BadUnknownObject1 final - : public SomeVirtualClass - , public Mso::UnknownObject + : public SomeVirtualClass + , public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(BadUnknownObject1); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(BadUnknownObject1); - virtual int GetValue1() const override - { - return 1; - } + virtual int GetValue1() const override + { + return 1; + } private: - BadUnknownObject1() = default; + BadUnknownObject1() = default; }; #endif #ifdef TEST_BAD_INHERITANCE2 // !!! Mso::UnknownObject must be always the first one in the inheritance !!! class BadUnknownObject2 final - : public SomeVirtualClass - , public Mso::UnknownObject + : public SomeVirtualClass + , public Mso::UnknownObject { - friend MakePolicy; // To allow constructor to be private or protected. + friend MakePolicy; // To allow constructor to be private or protected. public: - virtual int GetValue1() const override - { - return 1; - } + virtual int GetValue1() const override + { + return 1; + } private: - BadUnknownObject1() = default; + BadUnknownObject1() = default; }; #endif -class MyMemHeapUnknownSample1 final - : public Mso::UnknownObject +class MyMemHeapUnknownSample1 final : public Mso::UnknownObject { public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } protected: - friend MakePolicy; + friend MakePolicy; - MyMemHeapUnknownSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + MyMemHeapUnknownSample1(bool& deleted) noexcept : m_deleted(deleted) {} - virtual ~MyMemHeapUnknownSample1() noexcept - { - m_deleted = true; - } + virtual ~MyMemHeapUnknownSample1() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; -class MyMemHeapUnknownSample2 final - : public Mso::UnknownObject +class MyMemHeapUnknownSample2 final : public Mso::UnknownObject { public: - virtual int GetValue1() const noexcept override - { - return 1; - } + virtual int GetValue1() const noexcept override + { + return 1; + } protected: - friend MakePolicy; + friend MakePolicy; - MyMemHeapUnknownSample2(bool& deleted) noexcept - : m_deleted(deleted) - { - } + MyMemHeapUnknownSample2(bool& deleted) noexcept : m_deleted(deleted) {} - virtual ~MyMemHeapUnknownSample2() noexcept - { - m_deleted = true; - } + virtual ~MyMemHeapUnknownSample2() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; -TEST_CLASS(UnknownObjectTest) +TEST_CLASS (UnknownObjectTest) { - TEST_METHOD(UnknownObject_SimpleRefCount_OneBaseInterface) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - Debug(TestAssert::AreEqual(1, unknown1->RefCount())); + TEST_METHOD(UnknownObject_SimpleRefCount_OneBaseInterface) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + Debug(TestAssert::AreEqual(1, unknown1->RefCount())); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, unknown1->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, unknown1->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleRefCount_InitializeThis_OneBaseInterface) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - Debug(TestAssert::AreEqual(1, unknown1->RefCount())); + TEST_METHOD(UnknownObject_SimpleRefCount_InitializeThis_OneBaseInterface) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + Debug(TestAssert::AreEqual(1, unknown1->RefCount())); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, unknown1->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, unknown1->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleRefCount_TwoBaseInterfaces) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - Debug(TestAssert::AreEqual(1, unknown1->RefCount())); + TEST_METHOD(UnknownObject_SimpleRefCount_TwoBaseInterfaces) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + Debug(TestAssert::AreEqual(1, unknown1->RefCount())); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, unknown1->RefCount())); + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, unknown1->RefCount())); - Mso::TCntPtr base2 = unknown1; - TestAssert::AreEqual(2, base2->GetValue2()); - Debug(TestAssert::AreEqual(3, unknown1->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base2 = unknown1; + TestAssert::AreEqual(2, base2->GetValue2()); + Debug(TestAssert::AreEqual(3, unknown1->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleRefCount_TwoBaseInterfacesAndDerived) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - Debug(TestAssert::AreEqual(1, unknown1->RefCount())); + TEST_METHOD(UnknownObject_SimpleRefCount_TwoBaseInterfacesAndDerived) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + Debug(TestAssert::AreEqual(1, unknown1->RefCount())); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, unknown1->RefCount())); + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, unknown1->RefCount())); - Mso::TCntPtr base2 = unknown1; - TestAssert::AreEqual(2, base2->GetValue2()); - Debug(TestAssert::AreEqual(3, unknown1->RefCount())); + Mso::TCntPtr base2 = unknown1; + TestAssert::AreEqual(2, base2->GetValue2()); + Debug(TestAssert::AreEqual(3, unknown1->RefCount())); - Mso::TCntPtr unknown2 = qi_cast(base2.Get()); - TestAssert::AreEqual(2, unknown2->GetValue2()); - Debug(TestAssert::AreEqual(4, unknown1->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr unknown2 = qi_cast(base2.Get()); + TestAssert::AreEqual(2, unknown2->GetValue2()); + Debug(TestAssert::AreEqual(4, unknown1->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_WeakRefCount_ObjectWithWeakRefBase) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - Debug(TestAssert::AreEqual(1, unknown1->GetWeakRef().RefCount())); + TEST_METHOD(UnknownObject_WeakRefCount_ObjectWithWeakRefBase) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + Debug(TestAssert::AreEqual(1, unknown1->GetWeakRef().RefCount())); - Mso::TCntPtr base1 = unknown1; - Debug(TestAssert::AreEqual(2, unknown1->GetWeakRef().RefCount())); + Mso::TCntPtr base1 = unknown1; + Debug(TestAssert::AreEqual(2, unknown1->GetWeakRef().RefCount())); - Mso::ObjectWeakRef* obj1weakRef = query_cast(base1.Get()); - TestAssert::IsNotNull(obj1weakRef); - Debug(TestAssert::AreEqual(2, obj1weakRef->RefCount())); - } - TestAssert::IsTrue(deleted); - } + Mso::ObjectWeakRef* obj1weakRef = query_cast(base1.Get()); + TestAssert::IsNotNull(obj1weakRef); + Debug(TestAssert::AreEqual(2, obj1weakRef->RefCount())); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_WeakRefCount_OneInterface) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::WeakPtr weakPtr1; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); + TEST_METHOD(UnknownObject_WeakRefCount_OneInterface) + { + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::WeakPtr weakPtr1; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); - weakPtr = unknown1; - Mso::TCntPtr unknown11 = weakPtr.GetStrongPtr(); - TestAssert::IsNotNull(unknown11.Get()); - TestAssert::IsFalse(weakPtr.IsExpired()); + weakPtr = unknown1; + Mso::TCntPtr unknown11 = weakPtr.GetStrongPtr(); + TestAssert::IsNotNull(unknown11.Get()); + TestAssert::IsFalse(weakPtr.IsExpired()); - weakPtr1 = base1; - Mso::TCntPtr base11 = weakPtr1.GetStrongPtr(); - TestAssert::IsNotNull(base11.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); - } - TestAssert::IsTrue(deleted); - Mso::TCntPtr unknown12 = weakPtr.GetStrongPtr(); - TestAssert::IsNull(unknown12.Get()); - TestAssert::IsTrue(weakPtr1.IsExpired()); - } - } + weakPtr1 = base1; + Mso::TCntPtr base11 = weakPtr1.GetStrongPtr(); + TestAssert::IsNotNull(base11.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); + } + TestAssert::IsTrue(deleted); + Mso::TCntPtr unknown12 = weakPtr.GetStrongPtr(); + TestAssert::IsNull(unknown12.Get()); + TestAssert::IsTrue(weakPtr1.IsExpired()); + } + } - TEST_METHOD(UnknownObject_WeakRefCount_TwoInterfaces) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::WeakPtr weakPtr1; - Mso::WeakPtr weakPtr2; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); + TEST_METHOD(UnknownObject_WeakRefCount_TwoInterfaces) + { + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::WeakPtr weakPtr1; + Mso::WeakPtr weakPtr2; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); - Mso::TCntPtr base2 = unknown1; - TestAssert::AreEqual(2, base2->GetValue2()); + Mso::TCntPtr base2 = unknown1; + TestAssert::AreEqual(2, base2->GetValue2()); - Mso::TCntPtr base11 = qi_cast(base2.Get()); - TestAssert::IsTrue(base1.Get() == base11.Get(), L"Expected the same IBaseSample1 pointer"); + Mso::TCntPtr base11 = qi_cast(base2.Get()); + TestAssert::IsTrue(base1.Get() == base11.Get(), L"Expected the same IBaseSample1 pointer"); - weakPtr = unknown1; - Mso::TCntPtr unknown11 = weakPtr.GetStrongPtr(); - TestAssert::IsNotNull(unknown11.Get()); - TestAssert::IsFalse(weakPtr.IsExpired()); + weakPtr = unknown1; + Mso::TCntPtr unknown11 = weakPtr.GetStrongPtr(); + TestAssert::IsNotNull(unknown11.Get()); + TestAssert::IsFalse(weakPtr.IsExpired()); - weakPtr1 = base1; - Mso::TCntPtr base12 = weakPtr1.GetStrongPtr(); - TestAssert::IsNotNull(base12.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); + weakPtr1 = base1; + Mso::TCntPtr base12 = weakPtr1.GetStrongPtr(); + TestAssert::IsNotNull(base12.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); - weakPtr2 = base2; - Mso::TCntPtr base21 = weakPtr2.GetStrongPtr(); - TestAssert::IsNotNull(base21.Get()); - TestAssert::IsFalse(weakPtr2.IsExpired()); - } - TestAssert::IsTrue(deleted); - Mso::TCntPtr unknown12 = weakPtr.GetStrongPtr(); - TestAssert::IsNull(unknown12.Get()); - TestAssert::IsTrue(weakPtr1.IsExpired()); - } - } + weakPtr2 = base2; + Mso::TCntPtr base21 = weakPtr2.GetStrongPtr(); + TestAssert::IsNotNull(base21.Get()); + TestAssert::IsFalse(weakPtr2.IsExpired()); + } + TestAssert::IsTrue(deleted); + Mso::TCntPtr unknown12 = weakPtr.GetStrongPtr(); + TestAssert::IsNull(unknown12.Get()); + TestAssert::IsTrue(weakPtr1.IsExpired()); + } + } - TEST_METHOD(UnknownObject_WeakRefCount_TwoInterfacesAndDerived) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::WeakPtr weakPtr1; - Mso::WeakPtr weakPtr2; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); + TEST_METHOD(UnknownObject_WeakRefCount_TwoInterfacesAndDerived) + { + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::WeakPtr weakPtr1; + Mso::WeakPtr weakPtr2; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); - Mso::TCntPtr base2 = unknown1; - TestAssert::AreEqual(2, base2->GetValue2()); + Mso::TCntPtr base2 = unknown1; + TestAssert::AreEqual(2, base2->GetValue2()); - Mso::TCntPtr unknown2 = qi_cast(base1.Get()); - TestAssert::IsTrue(unknown1.Get() == unknown2.Get(), L"Expected the same UnknownSample6 instance"); + Mso::TCntPtr unknown2 = qi_cast(base1.Get()); + TestAssert::IsTrue(unknown1.Get() == unknown2.Get(), L"Expected the same UnknownSample6 instance"); - Mso::TCntPtr unknown3 = qi_cast(base2.Get()); - TestAssert::IsTrue(unknown1.Get() == unknown3.Get(), L"Expected the same UnknownSample6 instance"); + Mso::TCntPtr unknown3 = qi_cast(base2.Get()); + TestAssert::IsTrue(unknown1.Get() == unknown3.Get(), L"Expected the same UnknownSample6 instance"); - weakPtr = unknown1; - Mso::TCntPtr unknown11 = weakPtr.GetStrongPtr(); - TestAssert::IsNotNull(unknown11.Get()); - TestAssert::IsFalse(weakPtr.IsExpired()); + weakPtr = unknown1; + Mso::TCntPtr unknown11 = weakPtr.GetStrongPtr(); + TestAssert::IsNotNull(unknown11.Get()); + TestAssert::IsFalse(weakPtr.IsExpired()); - weakPtr1 = base1; - Mso::TCntPtr base11 = weakPtr1.GetStrongPtr(); - TestAssert::IsNotNull(base11.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); + weakPtr1 = base1; + Mso::TCntPtr base11 = weakPtr1.GetStrongPtr(); + TestAssert::IsNotNull(base11.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); - weakPtr2 = base2; - Mso::TCntPtr base21 = weakPtr2.GetStrongPtr(); - TestAssert::IsNotNull(base21.Get()); - TestAssert::IsFalse(weakPtr2.IsExpired()); - } - TestAssert::IsTrue(deleted); - Mso::TCntPtr unknown12 = weakPtr.GetStrongPtr(); - TestAssert::IsNull(unknown12.Get()); - TestAssert::IsTrue(weakPtr1.IsExpired()); - } - } + weakPtr2 = base2; + Mso::TCntPtr base21 = weakPtr2.GetStrongPtr(); + TestAssert::IsNotNull(base21.Get()); + TestAssert::IsFalse(weakPtr2.IsExpired()); + } + TestAssert::IsTrue(deleted); + Mso::TCntPtr unknown12 = weakPtr.GetStrongPtr(); + TestAssert::IsNull(unknown12.Get()); + TestAssert::IsTrue(weakPtr1.IsExpired()); + } + } - TEST_METHOD(UnknownObject_QueryForBaseInterface) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base2 = qi_cast(unknown1.Get()); - TestAssert::IsNotNull(base2.Get()); - TestAssert::AreEqual(2, base2->GetValue2()); - Mso::TCntPtr base1 = qi_cast(base2.Get()); - TestAssert::IsNotNull(base1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - Mso::TCntPtr derivedBase1 = qi_cast(base2.Get()); - TestAssert::IsNotNull(derivedBase1.Get()); - TestAssert::AreEqual(11, derivedBase1->GetValue11()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_QueryForBaseInterface) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base2 = qi_cast(unknown1.Get()); + TestAssert::IsNotNull(base2.Get()); + TestAssert::AreEqual(2, base2->GetValue2()); + Mso::TCntPtr base1 = qi_cast(base2.Get()); + TestAssert::IsNotNull(base1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + Mso::TCntPtr derivedBase1 = qi_cast(base2.Get()); + TestAssert::IsNotNull(derivedBase1.Get()); + TestAssert::AreEqual(11, derivedBase1->GetValue11()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_NoRefCount_Stack) - { - bool deleted = false; - { - UnknownSample8 unknown1(/*ref*/deleted); - Mso::TCntPtr base2 = qi_cast(&unknown1); - TestAssert::IsNull(base2.Get()); - Mso::TCntPtr base1 = qi_cast(&unknown1); - TestAssert::IsNotNull(base1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_NoRefCount_Stack) + { + bool deleted = false; + { + UnknownSample8 unknown1(/*ref*/ deleted); + Mso::TCntPtr base2 = qi_cast(&unknown1); + TestAssert::IsNull(base2.Get()); + Mso::TCntPtr base1 = qi_cast(&unknown1); + TestAssert::IsNotNull(base1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_NoRefCount_UniquePtr) - { - bool deleted = false; - { - std::unique_ptr unknown1 = std::make_unique(/*ref*/deleted); - Mso::TCntPtr base2 = qi_cast(unknown1.get()); - TestAssert::IsNull(base2.Get()); - Mso::TCntPtr base1 = qi_cast(unknown1.get()); - TestAssert::IsNotNull(base1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_NoRefCount_UniquePtr) + { + bool deleted = false; + { + std::unique_ptr unknown1 = std::make_unique(/*ref*/ deleted); + Mso::TCntPtr base2 = qi_cast(unknown1.get()); + TestAssert::IsNull(base2.Get()); + Mso::TCntPtr base1 = qi_cast(unknown1.get()); + TestAssert::IsNotNull(base1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_NonDefaultBaseConstructor) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = qi_cast(unknown1.Get()); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(UnknownObject_NonDefaultBaseConstructor) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = qi_cast(unknown1.Get()); + TestAssert::AreEqual(0, base1->GetValue1()); - Mso::TCntPtr unknown2 = Mso::Make(/*ref*/deleted, 3); - Mso::TCntPtr base2 = qi_cast(unknown2.Get()); - TestAssert::AreEqual(3, base2->GetValue1()); + Mso::TCntPtr unknown2 = Mso::Make(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = qi_cast(unknown2.Get()); + TestAssert::AreEqual(3, base2->GetValue1()); - Mso::TCntPtr unknown3 = Mso::Make(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = qi_cast(unknown3.Get()); - TestAssert::AreEqual(8, base3->GetValue1()); + Mso::TCntPtr unknown3 = Mso::Make(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = qi_cast(unknown3.Get()); + TestAssert::AreEqual(8, base3->GetValue1()); - Mso::TCntPtr unknown4 = Mso::Make(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = qi_cast(unknown4.Get()); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr unknown4 = Mso::Make(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = qi_cast(unknown4.Get()); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_WeakRef_NonDefaultBaseConstructor) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = qi_cast(unknown1.Get()); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(UnknownObject_WeakRef_NonDefaultBaseConstructor) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = qi_cast(unknown1.Get()); + TestAssert::AreEqual(0, base1->GetValue1()); - Mso::TCntPtr unknown2 = Mso::Make(/*ref*/deleted, 3); - Mso::TCntPtr base2 = qi_cast(unknown2.Get()); - TestAssert::AreEqual(3, base2->GetValue1()); + Mso::TCntPtr unknown2 = Mso::Make(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = qi_cast(unknown2.Get()); + TestAssert::AreEqual(3, base2->GetValue1()); - Mso::TCntPtr unknown3 = Mso::Make(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = qi_cast(unknown3.Get()); - TestAssert::AreEqual(8, base3->GetValue1()); + Mso::TCntPtr unknown3 = Mso::Make(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = qi_cast(unknown3.Get()); + TestAssert::AreEqual(8, base3->GetValue1()); - Mso::TCntPtr unknown4 = Mso::Make(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = qi_cast(unknown4.Get()); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr unknown4 = Mso::Make(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = qi_cast(unknown4.Get()); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_NoRefCount_NonDefaultBaseConstructor) - { - bool deleted = false; - { - UnknownSample93 unknown1(/*ref*/deleted); - Mso::TCntPtr base1 = qi_cast(&unknown1); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(UnknownObject_NoRefCount_NonDefaultBaseConstructor) + { + bool deleted = false; + { + UnknownSample93 unknown1(/*ref*/ deleted); + Mso::TCntPtr base1 = qi_cast(&unknown1); + TestAssert::AreEqual(0, base1->GetValue1()); - UnknownSample93 unknown2(/*ref*/deleted, 3); - Mso::TCntPtr base2 = qi_cast(&unknown2); - TestAssert::AreEqual(3, base2->GetValue1()); + UnknownSample93 unknown2(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = qi_cast(&unknown2); + TestAssert::AreEqual(3, base2->GetValue1()); - UnknownSample93 unknown3(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = qi_cast(&unknown3); - TestAssert::AreEqual(8, base3->GetValue1()); + UnknownSample93 unknown3(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = qi_cast(&unknown3); + TestAssert::AreEqual(8, base3->GetValue1()); - UnknownSample93 unknown4(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = qi_cast(&unknown4); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + UnknownSample93 unknown4(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = qi_cast(&unknown4); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_NoRefCountNoQuery_NonDefaultBaseConstructor) - { - bool deleted = false; - { - UnknownSample94 unknown1(/*ref*/deleted); - TestAssert::AreEqual(0, unknown1.GetValue1()); + TEST_METHOD(UnknownObject_NoRefCountNoQuery_NonDefaultBaseConstructor) + { + bool deleted = false; + { + UnknownSample94 unknown1(/*ref*/ deleted); + TestAssert::AreEqual(0, unknown1.GetValue1()); - UnknownSample94 unknown2(/*ref*/deleted, 3); - TestAssert::AreEqual(3, unknown2.GetValue1()); + UnknownSample94 unknown2(/*ref*/ deleted, 3); + TestAssert::AreEqual(3, unknown2.GetValue1()); - UnknownSample94 unknown3(/*ref*/deleted, 3, 5); - TestAssert::AreEqual(8, unknown3.GetValue1()); + UnknownSample94 unknown3(/*ref*/ deleted, 3, 5); + TestAssert::AreEqual(8, unknown3.GetValue1()); - UnknownSample94 unknown4(/*ref*/deleted, 3, 5, 11); - TestAssert::AreEqual(19, unknown4.GetValue1()); - } - TestAssert::IsTrue(deleted); - } + UnknownSample94 unknown4(/*ref*/ deleted, 3, 5, 11); + TestAssert::AreEqual(19, unknown4.GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_DestroyThis) - { - Mso::Async::ManualResetEvent deleted; - bool isAsyncDestroy = false; + TEST_METHOD(UnknownObject_DestroyThis) + { + Mso::Async::ManualResetEvent deleted; + bool isAsyncDestroy = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted, /*ref*/isAsyncDestroy); - Mso::TCntPtr base1 = qi_cast(unknown1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - } + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted, /*ref*/ isAsyncDestroy); + Mso::TCntPtr base1 = qi_cast(unknown1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + } - // Wait for deletion to complete - deleted.Wait(); - TestAssert::IsTrue(isAsyncDestroy); - } + // Wait for deletion to complete + deleted.Wait(); + TestAssert::IsTrue(isAsyncDestroy); + } - TEST_METHOD(UnknownObject_WeakRef_DestroyThis) - { - Mso::Async::ManualResetEvent deleted; - bool isAsyncDestroy = false; + TEST_METHOD(UnknownObject_WeakRef_DestroyThis) + { + Mso::Async::ManualResetEvent deleted; + bool isAsyncDestroy = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted, /*ref*/isAsyncDestroy); - Mso::TCntPtr base1 = qi_cast(unknown1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - } + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted, /*ref*/ isAsyncDestroy); + Mso::TCntPtr base1 = qi_cast(unknown1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + } - // Wait for deletion to complete - deleted.Wait(); - TestAssert::IsTrue(isAsyncDestroy); - } + // Wait for deletion to complete + deleted.Wait(); + TestAssert::IsTrue(isAsyncDestroy); + } - TEST_METHOD(UnknownObject_QI_NullPtr) - { - Mso::TCntPtr base1 = Mso::Make(); + TEST_METHOD(UnknownObject_QI_NullPtr) + { + Mso::TCntPtr base1 = Mso::Make(); - TestCheckCrash( - OACR_WARNING_SUPPRESS(INVALID_PARAM_VALUE_1, "Invalid parameter value. Our goal here is to see runtime check for the invalid value"); - (void)base1->QueryInterface(__uuidof(IBaseSample2), nullptr); - ); - } + TestCheckCrash(OACR_WARNING_SUPPRESS( + INVALID_PARAM_VALUE_1, + "Invalid parameter value. Our goal here is to see runtime check for the invalid value"); + (void)base1->QueryInterface(__uuidof(IBaseSample2), nullptr);); + } - TEST_METHOD(UnknownObject_NoRefCountNoQuery_Stack) - { - bool deleted = false; - { - UnknownSample12 unknown1(/*ref*/deleted); - Mso::TCntPtr base2 = qi_cast(&unknown1); - TestAssert::IsNull(base2.Get()); - Mso::TCntPtr base1 = qi_cast(&unknown1); - TestAssert::IsNull(base1.Get()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_NoRefCountNoQuery_Stack) + { + bool deleted = false; + { + UnknownSample12 unknown1(/*ref*/ deleted); + Mso::TCntPtr base2 = qi_cast(&unknown1); + TestAssert::IsNull(base2.Get()); + Mso::TCntPtr base1 = qi_cast(&unknown1); + TestAssert::IsNull(base1.Get()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_NoRefCountNoQuery_UniquePtr) - { - bool deleted = false; - { - std::unique_ptr unknown1 = std::make_unique(/*ref*/deleted); - Mso::TCntPtr base2 = qi_cast(unknown1.get()); - TestAssert::IsNull(base2.Get()); - Mso::TCntPtr base1 = qi_cast(unknown1.get()); - TestAssert::IsNull(base1.Get()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_NoRefCountNoQuery_UniquePtr) + { + bool deleted = false; + { + std::unique_ptr unknown1 = std::make_unique(/*ref*/ deleted); + Mso::TCntPtr base2 = qi_cast(unknown1.get()); + TestAssert::IsNull(base2.Get()); + Mso::TCntPtr base1 = qi_cast(unknown1.get()); + TestAssert::IsNull(base1.Get()); + } + TestAssert::IsTrue(deleted); + } #if defined(MSO_ENABLE_QICHECK) && defined(DEBUG) && !defined(__clang__) - TESTMETHOD_REQUIRES_SEH(UnknownObject_QI_NotNullResult) - { - Mso::TCntPtr base1 = Mso::Make(); - Mso::TCntPtr base2 = Mso::Make(); + TESTMETHOD_REQUIRES_SEH(UnknownObject_QI_NotNullResult) + { + Mso::TCntPtr base1 = Mso::Make(); + Mso::TCntPtr base2 = Mso::Make(); - TestAssert::ExpectVEC([&]() noexcept - { - base1->QueryInterface(__uuidof(IBaseSample2), reinterpret_cast(base2.GetRaw())); - }); - } + TestAssert::ExpectVEC( + [&]() noexcept { base1->QueryInterface(__uuidof(IBaseSample2), reinterpret_cast(base2.GetRaw())); }); + } #endif - TEST_METHOD(AgileUnknownObject_SimpleRefCount) - { - bool deleted = false; - { - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - Debug(TestAssert::AreEqual(1, unknown1->RefCount())); + TEST_METHOD(AgileUnknownObject_SimpleRefCount) + { + bool deleted = false; + { + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + Debug(TestAssert::AreEqual(1, unknown1->RefCount())); - Mso::TCntPtr base1 = unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, unknown1->RefCount())); + Mso::TCntPtr base1 = unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, unknown1->RefCount())); #if defined(MS_TARGET_WINDOWS) - Mso::TCntPtr marshal1 = qi_cast(base1.Get()); - TestAssert::IsNotNull(marshal1.Get(), L"IMarshal must not be null."); - Debug(TestAssert::AreEqual(3, unknown1->RefCount())); - - Mso::TCntPtr agile1 = qi_cast(base1.Get()); - TestAssert::IsNotNull(agile1.Get(), L"IAgileObject must not be null."); - Debug(TestAssert::AreEqual(4, unknown1->RefCount())); -#endif - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr marshal1 = qi_cast(base1.Get()); + TestAssert::IsNotNull(marshal1.Get(), L"IMarshal must not be null."); + Debug(TestAssert::AreEqual(3, unknown1->RefCount())); - TEST_METHOD(AgileUnknownObject_WeakRefCount) - { - bool deleted = false; - { - Mso::WeakPtr weakAgile; - Mso::WeakPtr weakBase1; + Mso::TCntPtr agile1 = qi_cast(base1.Get()); + TestAssert::IsNotNull(agile1.Get(), L"IAgileObject must not be null."); + Debug(TestAssert::AreEqual(4, unknown1->RefCount())); +#endif + } + TestAssert::IsTrue(deleted); + } + + TEST_METHOD(AgileUnknownObject_WeakRefCount) + { + bool deleted = false; + { + Mso::WeakPtr weakAgile; + Mso::WeakPtr weakBase1; #if !defined(__clang__) && !defined(__GNUC__) - Mso::WeakPtr weakMarshal; - Mso::WeakPtr weakAgileObj; + Mso::WeakPtr weakMarshal; + Mso::WeakPtr weakAgileObj; #endif - { - Mso::TCntPtr agile1 = Mso::Make(/*ref*/deleted); - TestAssert::AreEqual(1, agile1->GetValue1()); - Debug(TestAssert::AreEqual(1, agile1->GetWeakRef().RefCount())); + { + Mso::TCntPtr agile1 = Mso::Make(/*ref*/ deleted); + TestAssert::AreEqual(1, agile1->GetValue1()); + Debug(TestAssert::AreEqual(1, agile1->GetWeakRef().RefCount())); - Mso::TCntPtr base1 = qi_cast(agile1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - Debug(TestAssert::AreEqual(2, agile1->GetWeakRef().RefCount())); + Mso::TCntPtr base1 = qi_cast(agile1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + Debug(TestAssert::AreEqual(2, agile1->GetWeakRef().RefCount())); #if !defined(__clang__) && !defined(__GNUC__) - Mso::TCntPtr marshal1 = qi_cast(base1.Get()); - TestAssert::IsNotNull(marshal1.Get(), L"IMarshal must not be null."); - Debug(TestAssert::AreEqual(3, agile1->GetWeakRef().RefCount())); + Mso::TCntPtr marshal1 = qi_cast(base1.Get()); + TestAssert::IsNotNull(marshal1.Get(), L"IMarshal must not be null."); + Debug(TestAssert::AreEqual(3, agile1->GetWeakRef().RefCount())); - Mso::TCntPtr agileObj1 = qi_cast(marshal1.Get()); - TestAssert::IsNotNull(agileObj1.Get(), L"IAgileObject must not be null."); - Debug(TestAssert::AreEqual(4, agile1->GetWeakRef().RefCount())); + Mso::TCntPtr agileObj1 = qi_cast(marshal1.Get()); + TestAssert::IsNotNull(agileObj1.Get(), L"IAgileObject must not be null."); + Debug(TestAssert::AreEqual(4, agile1->GetWeakRef().RefCount())); #endif - weakAgile = agile1; - Mso::TCntPtr agile11 = weakAgile.GetStrongPtr(); - TestAssert::IsNotNull(agile11.Get()); - TestAssert::IsFalse(weakAgile.IsExpired()); + weakAgile = agile1; + Mso::TCntPtr agile11 = weakAgile.GetStrongPtr(); + TestAssert::IsNotNull(agile11.Get()); + TestAssert::IsFalse(weakAgile.IsExpired()); - weakBase1 = base1; - Mso::TCntPtr base11 = weakBase1.GetStrongPtr(); - TestAssert::IsNotNull(base11.Get()); - TestAssert::IsFalse(weakBase1.IsExpired()); + weakBase1 = base1; + Mso::TCntPtr base11 = weakBase1.GetStrongPtr(); + TestAssert::IsNotNull(base11.Get()); + TestAssert::IsFalse(weakBase1.IsExpired()); #if !defined(__clang__) && !defined(__GNUC__) - weakMarshal = marshal1; - Mso::TCntPtr marshal11 = weakMarshal.GetStrongPtr(); - TestAssert::IsNotNull(marshal11.Get()); - TestAssert::IsFalse(weakMarshal.IsExpired()); + weakMarshal = marshal1; + Mso::TCntPtr marshal11 = weakMarshal.GetStrongPtr(); + TestAssert::IsNotNull(marshal11.Get()); + TestAssert::IsFalse(weakMarshal.IsExpired()); - weakAgileObj = agileObj1; - Mso::TCntPtr agileObj11 = weakAgileObj.GetStrongPtr(); - TestAssert::IsNotNull(agileObj11.Get()); - TestAssert::IsFalse(weakAgileObj.IsExpired()); + weakAgileObj = agileObj1; + Mso::TCntPtr agileObj11 = weakAgileObj.GetStrongPtr(); + TestAssert::IsNotNull(agileObj11.Get()); + TestAssert::IsFalse(weakAgileObj.IsExpired()); #endif - } - TestAssert::IsTrue(deleted); - Mso::TCntPtr agile12 = weakAgile.GetStrongPtr(); - TestAssert::IsNull(agile12.Get()); - TestAssert::IsTrue(weakAgile.IsExpired()); - } - } + } + TestAssert::IsTrue(deleted); + Mso::TCntPtr agile12 = weakAgile.GetStrongPtr(); + TestAssert::IsNull(agile12.Get()); + TestAssert::IsTrue(weakAgile.IsExpired()); + } + } - TEST_METHOD(AgileUnknownObject_NoRefCount_Stack) - { - bool deleted = false; - { - AgileSample3 agile1(/*ref*/deleted); + TEST_METHOD(AgileUnknownObject_NoRefCount_Stack) + { + bool deleted = false; + { + AgileSample3 agile1(/*ref*/ deleted); #if !defined(__clang__) && !defined(__GNUC__) - Mso::TCntPtr marshal1 = qi_cast(&agile1); - TestAssert::IsNotNull(marshal1.Get()); + Mso::TCntPtr marshal1 = qi_cast(&agile1); + TestAssert::IsNotNull(marshal1.Get()); - Mso::TCntPtr base1 = qi_cast(marshal1.Get()); - TestAssert::IsNotNull(base1.Get()); + Mso::TCntPtr base1 = qi_cast(marshal1.Get()); + TestAssert::IsNotNull(base1.Get()); - Mso::TCntPtr agileObj1 = qi_cast(base1.Get()); - TestAssert::IsNotNull(agileObj1.Get()); + Mso::TCntPtr agileObj1 = qi_cast(base1.Get()); + TestAssert::IsNotNull(agileObj1.Get()); #endif - Mso::TCntPtr base11 = qi_cast(&agile1); - TestAssert::IsNotNull(base11.Get()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base11 = qi_cast(&agile1); + TestAssert::IsNotNull(base11.Get()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(AgileUnknownObject_NoRefCount_UniquePtr) - { - bool deleted = false; - { - std::unique_ptr agile1 = std::make_unique(/*ref*/deleted); + TEST_METHOD(AgileUnknownObject_NoRefCount_UniquePtr) + { + bool deleted = false; + { + std::unique_ptr agile1 = std::make_unique(/*ref*/ deleted); #if !defined(__clang__) && !defined(__GNUC__) - Mso::TCntPtr marshal1 = qi_cast(agile1.get()); - TestAssert::IsNotNull(marshal1.Get()); + Mso::TCntPtr marshal1 = qi_cast(agile1.get()); + TestAssert::IsNotNull(marshal1.Get()); - Mso::TCntPtr base1 = qi_cast(marshal1.Get()); - TestAssert::IsNotNull(base1.Get()); + Mso::TCntPtr base1 = qi_cast(marshal1.Get()); + TestAssert::IsNotNull(base1.Get()); - Mso::TCntPtr agileObj1 = qi_cast(base1.Get()); - TestAssert::IsNotNull(agileObj1.Get()); + Mso::TCntPtr agileObj1 = qi_cast(base1.Get()); + TestAssert::IsNotNull(agileObj1.Get()); #endif - Mso::TCntPtr base11 = qi_cast(agile1.get()); - TestAssert::IsNotNull(base11.Get()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr base11 = qi_cast(agile1.get()); + TestAssert::IsNotNull(base11.Get()); + } + TestAssert::IsTrue(deleted); + } // OM:2065596: Investigate why this test fails sth.exe for winrt nx64. #if !defined(TESTWINRT) && !defined(__clang__) && !defined(__GNUC__) - // Make sure that we initialize marshaller atomically - TEST_METHOD(AgileUnknownObject_SimpleRefCount_ThreadSafety) - { - // Run this test several times - for (int testIteration = 0; testIteration < 20; ++testIteration) - { - // Create an array of threads and ask for IMarshal in each thread, - // store them in an array and see that we got the same result for all cases. - const size_t threadCount = 20; - std::vector threads; - threads.reserve(20); + // Make sure that we initialize marshaller atomically + TEST_METHOD(AgileUnknownObject_SimpleRefCount_ThreadSafety) + { + // Run this test several times + for (int testIteration = 0; testIteration < 20; ++testIteration) + { + // Create an array of threads and ask for IMarshal in each thread, + // store them in an array and see that we got the same result for all cases. + const size_t threadCount = 20; + std::vector threads; + threads.reserve(20); - std::vector> results; - results.resize(threadCount); + std::vector> results; + results.resize(threadCount); - bool deleted = false; - Mso::TCntPtr agile1 = Mso::Make(/*ref*/deleted); + bool deleted = false; + Mso::TCntPtr agile1 = Mso::Make(/*ref*/ deleted); - for (size_t i = 0; i < threadCount; ++i) - { - threads.push_back(std::thread([&](size_t index) -> void - { - results[index] = qi_cast(agile1.Get()); - }, i)); - } + for (size_t i = 0; i < threadCount; ++i) + { + threads.push_back( + std::thread([&](size_t index) -> void { results[index] = qi_cast(agile1.Get()); }, i)); + } - // Wait until all threads finish - for (auto& t : threads) - { - t.join(); - } + // Wait until all threads finish + for (auto& t : threads) + { + t.join(); + } - // See that we have the same result - Mso::TCntPtr expected = qi_cast(agile1.Get()); - TestAssert::IsNotNull(expected.Get(), L"Expected not null IMarshal instance."); - for (const auto& result : results) - { - TestAssert::IsTrue(expected.Get() == result.Get(), L"IMarshal instances are different"); - } - } - } + // See that we have the same result + Mso::TCntPtr expected = qi_cast(agile1.Get()); + TestAssert::IsNotNull(expected.Get(), L"Expected not null IMarshal instance."); + for (const auto& result : results) + { + TestAssert::IsTrue(expected.Get() == result.Get(), L"IMarshal instances are different"); + } + } + } #endif - TEST_METHOD(AgileUnknownObject_NonDefaultBaseConstructor) - { - bool deleted = false; - { - Mso::TCntPtr agile1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = qi_cast(agile1.Get()); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(AgileUnknownObject_NonDefaultBaseConstructor) + { + bool deleted = false; + { + Mso::TCntPtr agile1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = qi_cast(agile1.Get()); + TestAssert::AreEqual(0, base1->GetValue1()); - Mso::TCntPtr agile2 = Mso::Make(/*ref*/deleted, 3); - Mso::TCntPtr base2 = qi_cast(agile2.Get()); - TestAssert::AreEqual(3, base2->GetValue1()); + Mso::TCntPtr agile2 = Mso::Make(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = qi_cast(agile2.Get()); + TestAssert::AreEqual(3, base2->GetValue1()); - Mso::TCntPtr agile3 = Mso::Make(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = qi_cast(agile3.Get()); - TestAssert::AreEqual(8, base3->GetValue1()); + Mso::TCntPtr agile3 = Mso::Make(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = qi_cast(agile3.Get()); + TestAssert::AreEqual(8, base3->GetValue1()); - Mso::TCntPtr agile4 = Mso::Make(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = qi_cast(agile4.Get()); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr agile4 = Mso::Make(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = qi_cast(agile4.Get()); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(AgileUnknownObject_WeakRef_NonDefaultBaseConstructor) - { - bool deleted = false; - { - Mso::TCntPtr agile1 = Mso::Make(/*ref*/deleted); - Mso::TCntPtr base1 = qi_cast(agile1.Get()); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(AgileUnknownObject_WeakRef_NonDefaultBaseConstructor) + { + bool deleted = false; + { + Mso::TCntPtr agile1 = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr base1 = qi_cast(agile1.Get()); + TestAssert::AreEqual(0, base1->GetValue1()); - Mso::TCntPtr agile2 = Mso::Make(/*ref*/deleted, 3); - Mso::TCntPtr base2 = qi_cast(agile2.Get()); - TestAssert::AreEqual(3, base2->GetValue1()); + Mso::TCntPtr agile2 = Mso::Make(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = qi_cast(agile2.Get()); + TestAssert::AreEqual(3, base2->GetValue1()); - Mso::TCntPtr agile3 = Mso::Make(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = qi_cast(agile3.Get()); - TestAssert::AreEqual(8, base3->GetValue1()); + Mso::TCntPtr agile3 = Mso::Make(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = qi_cast(agile3.Get()); + TestAssert::AreEqual(8, base3->GetValue1()); - Mso::TCntPtr agile4 = Mso::Make(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = qi_cast(agile4.Get()); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + Mso::TCntPtr agile4 = Mso::Make(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = qi_cast(agile4.Get()); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(AgileUnknownObject_NoRefCount_NonDefaultBaseConstructor) - { - bool deleted = false; - { - AgileSample43 agile1(/*ref*/deleted); - Mso::TCntPtr base1 = qi_cast(&agile1); - TestAssert::AreEqual(0, base1->GetValue1()); + TEST_METHOD(AgileUnknownObject_NoRefCount_NonDefaultBaseConstructor) + { + bool deleted = false; + { + AgileSample43 agile1(/*ref*/ deleted); + Mso::TCntPtr base1 = qi_cast(&agile1); + TestAssert::AreEqual(0, base1->GetValue1()); - AgileSample43 agile2(/*ref*/deleted, 3); - Mso::TCntPtr base2 = qi_cast(&agile2); - TestAssert::AreEqual(3, base2->GetValue1()); + AgileSample43 agile2(/*ref*/ deleted, 3); + Mso::TCntPtr base2 = qi_cast(&agile2); + TestAssert::AreEqual(3, base2->GetValue1()); - AgileSample43 agile3(/*ref*/deleted, 3, 5); - Mso::TCntPtr base3 = qi_cast(&agile3); - TestAssert::AreEqual(8, base3->GetValue1()); + AgileSample43 agile3(/*ref*/ deleted, 3, 5); + Mso::TCntPtr base3 = qi_cast(&agile3); + TestAssert::AreEqual(8, base3->GetValue1()); - AgileSample43 agile4(/*ref*/deleted, 3, 5, 11); - Mso::TCntPtr base4 = qi_cast(&agile4); - TestAssert::AreEqual(19, base4->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + AgileSample43 agile4(/*ref*/ deleted, 3, 5, 11); + Mso::TCntPtr base4 = qi_cast(&agile4); + TestAssert::AreEqual(19, base4->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_query_cast_null) - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - UnknownSample3* unknown1 = nullptr; - IBaseSample1* base1 = query_cast(unknown1); - TestAssert::IsNull(base1); - IBaseSample2* base2 = query_cast(base1); - TestAssert::IsNull(base2); - IBaseSample3* base3 = query_cast(base1); - TestAssert::IsNull(base3); - UnknownSample3* unknown2 = query_cast(base2); - TestAssert::IsNull(unknown2); - } + TEST_METHOD(UnknownObject_query_cast_null) + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + UnknownSample3* unknown1 = nullptr; + IBaseSample1* base1 = query_cast(unknown1); + TestAssert::IsNull(base1); + IBaseSample2* base2 = query_cast(base1); + TestAssert::IsNull(base2); + IBaseSample3* base3 = query_cast(base1); + TestAssert::IsNull(base3); + UnknownSample3* unknown2 = query_cast(base2); + TestAssert::IsNull(unknown2); + } - TEST_METHOD(UnknownObject_query_cast_const_null) - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - const UnknownSample3* unknown1 = nullptr; - const IBaseSample1* base1 = query_cast(unknown1); - TestAssert::IsNull(base1); - const IBaseSample2* base2 = query_cast(base1); - TestAssert::IsNull(base2); - const IBaseSample3* base3 = query_cast(base1); - TestAssert::IsNull(base3); - const UnknownSample3* unknown2 = query_cast(base2); - TestAssert::IsNull(unknown2); - } + TEST_METHOD(UnknownObject_query_cast_const_null) + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + const UnknownSample3* unknown1 = nullptr; + const IBaseSample1* base1 = query_cast(unknown1); + TestAssert::IsNull(base1); + const IBaseSample2* base2 = query_cast(base1); + TestAssert::IsNull(base2); + const IBaseSample3* base3 = query_cast(base1); + TestAssert::IsNull(base3); + const UnknownSample3* unknown2 = query_cast(base2); + TestAssert::IsNull(unknown2); + } - TEST_METHOD(UnknownObject_query_cast_ptr) - { - bool deleted = false; - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - IBaseSample1* base1 = query_cast(unknown1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - IBaseSample2* base2 = query_cast(base1); - TestAssert::AreEqual(2, base2->GetValue2()); - IBaseSample3* base3 = query_cast(base1); - TestAssert::IsNull(base3); - UnknownSample3* unknown2 = query_cast(base2); - OACR_USE_PTR(unknown2); // We do not want to make unknown2 const in this test. - TestAssert::AreEqual(2, unknown2->GetValue2()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_query_cast_ptr) + { + bool deleted = false; + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + IBaseSample1* base1 = query_cast(unknown1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + IBaseSample2* base2 = query_cast(base1); + TestAssert::AreEqual(2, base2->GetValue2()); + IBaseSample3* base3 = query_cast(base1); + TestAssert::IsNull(base3); + UnknownSample3* unknown2 = query_cast(base2); + OACR_USE_PTR(unknown2); // We do not want to make unknown2 const in this test. + TestAssert::AreEqual(2, unknown2->GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_query_cast_const_ptr) - { - bool deleted = false; - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - const IBaseSample1* base1 = query_cast(unknown1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - const IBaseSample2* base2 = query_cast(base1); - TestAssert::AreEqual(2, base2->GetValue2()); - const IBaseSample3* base3 = query_cast(base1); - TestAssert::IsNull(base3); - const UnknownSample3* unknown2 = query_cast(base2); - TestAssert::AreEqual(2, unknown2->GetValue2()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_query_cast_const_ptr) + { + bool deleted = false; + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + const IBaseSample1* base1 = query_cast(unknown1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + const IBaseSample2* base2 = query_cast(base1); + TestAssert::AreEqual(2, base2->GetValue2()); + const IBaseSample3* base3 = query_cast(base1); + TestAssert::IsNull(base3); + const UnknownSample3* unknown2 = query_cast(base2); + TestAssert::AreEqual(2, unknown2->GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_query_cast_const_ptr_from_ptr) - { - bool deleted = false; - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - const IBaseSample1* base1 = query_cast(unknown1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - const IBaseSample2* base2 = query_cast(const_cast(base1)); - TestAssert::AreEqual(2, base2->GetValue2()); - const IBaseSample3* base3 = query_cast(const_cast(base1)); - TestAssert::IsNull(base3); - const UnknownSample3* unknown2 = query_cast(const_cast(base2)); - TestAssert::AreEqual(2, unknown2->GetValue2()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_query_cast_const_ptr_from_ptr) + { + bool deleted = false; + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + const IBaseSample1* base1 = query_cast(unknown1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + const IBaseSample2* base2 = query_cast(const_cast(base1)); + TestAssert::AreEqual(2, base2->GetValue2()); + const IBaseSample3* base3 = query_cast(const_cast(base1)); + TestAssert::IsNull(base3); + const UnknownSample3* unknown2 = query_cast(const_cast(base2)); + TestAssert::AreEqual(2, unknown2->GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_query_cast_if_set_nullptr) - { - // UnknownSample111 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr base1 = Mso::Make(); - IBaseSample2* base2 = query_cast(base1.Get()); - TestAssert::AreEqual(2, base2->GetValue2()); - const IBaseSample1* base11 = query_cast(base2); - TestAssert::AreEqual(1, base11->GetValue1()); - IBaseSample3* base3 = query_cast(base1.Get()); - TestAssert::IsNull(base3); - } + TEST_METHOD(UnknownObject_query_cast_if_set_nullptr) + { + // UnknownSample111 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr base1 = Mso::Make(); + IBaseSample2* base2 = query_cast(base1.Get()); + TestAssert::AreEqual(2, base2->GetValue2()); + const IBaseSample1* base11 = query_cast(base2); + TestAssert::AreEqual(1, base11->GetValue1()); + IBaseSample3* base3 = query_cast(base1.Get()); + TestAssert::IsNull(base3); + } - TEST_METHOD(UnknownObject_query_cast_ref) - { - bool deleted = false; - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - IBaseSample1& base1 = query_cast(*unknown1); - TestAssert::AreEqual(1, base1.GetValue1()); - IBaseSample2& base2 = query_cast(base1); - TestAssert::AreEqual(2, base2.GetValue2()); - TestCheckCrash(query_cast(base1)); - UnknownSample3& unknown2 = query_cast(base2); - OACR_USE_PTR(&unknown2); // We do not want to make unknown2 const in this test. - TestAssert::AreEqual(2, unknown2.GetValue2()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_query_cast_ref) + { + bool deleted = false; + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + IBaseSample1& base1 = query_cast(*unknown1); + TestAssert::AreEqual(1, base1.GetValue1()); + IBaseSample2& base2 = query_cast(base1); + TestAssert::AreEqual(2, base2.GetValue2()); + TestCheckCrash(query_cast(base1)); + UnknownSample3& unknown2 = query_cast(base2); + OACR_USE_PTR(&unknown2); // We do not want to make unknown2 const in this test. + TestAssert::AreEqual(2, unknown2.GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_query_cast_const_ref) - { - bool deleted = false; - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - const IBaseSample1& base1 = query_cast(*unknown1); - TestAssert::AreEqual(1, base1.GetValue1()); - const IBaseSample2& base2 = query_cast(base1); + TEST_METHOD(UnknownObject_query_cast_const_ref) + { + bool deleted = false; + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + const IBaseSample1& base1 = query_cast(*unknown1); + TestAssert::AreEqual(1, base1.GetValue1()); + const IBaseSample2& base2 = query_cast(base1); - #if !__clang__ && !__GNUC__ // TODO: TestAssert::ExpectCrash is not implemented in clang. - TestAssert::AreEqual(2, base2.GetValue2()); - { - TestAssert::ExpectVEC([&]() noexcept - { - query_cast(base1); - }); - } - #endif //!__clang__ && !__GNUC__ +#if !__clang__ && !__GNUC__ // TODO: TestAssert::ExpectCrash is not implemented in clang. + TestAssert::AreEqual(2, base2.GetValue2()); + { + TestAssert::ExpectVEC([&]() noexcept { query_cast(base1); }); + } +#endif //!__clang__ && !__GNUC__ - const UnknownSample3& unknown2 = query_cast(base2); - TestAssert::AreEqual(2, unknown2.GetValue2()); - } - TestAssert::IsTrue(deleted); - } + const UnknownSample3& unknown2 = query_cast(base2); + TestAssert::AreEqual(2, unknown2.GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_query_cast_const_ref_from_ref) - { - bool deleted = false; - { - // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - const IBaseSample1& base1 = query_cast(const_cast(*unknown1)); - TestAssert::AreEqual(1, base1.GetValue1()); - const IBaseSample2& base2 = query_cast(const_cast(base1)); + TEST_METHOD(UnknownObject_query_cast_const_ref_from_ref) + { + bool deleted = false; + { + // UnknownSample3 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + const IBaseSample1& base1 = query_cast(const_cast(*unknown1)); + TestAssert::AreEqual(1, base1.GetValue1()); + const IBaseSample2& base2 = query_cast(const_cast(base1)); - #if !__clang__ && !__GNUC__ // TODO: TestAssert::ExpectCrash is not implemented in clang. - TestAssert::AreEqual(2, base2.GetValue2()); - { - TestAssert::ExpectVEC([&]() noexcept - { - query_cast(const_cast(base1)); - }); - } - #endif //!__clang__ && !__GNUC__ +#if !__clang__ && !__GNUC__ // TODO: TestAssert::ExpectCrash is not implemented in clang. + TestAssert::AreEqual(2, base2.GetValue2()); + { + TestAssert::ExpectVEC([&]() noexcept { query_cast(const_cast(base1)); }); + } +#endif //!__clang__ && !__GNUC__ - const UnknownSample3& unknown2 = query_cast(const_cast(base2)); - TestAssert::AreEqual(2, unknown2.GetValue2()); - } - TestAssert::IsTrue(deleted); - } + const UnknownSample3& unknown2 = query_cast(const_cast(base2)); + TestAssert::AreEqual(2, unknown2.GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_WeakRefCount_query_cast_ptr) - { - bool deleted = false; - { - // UnknownSample6 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - IBaseSample1* base1 = query_cast(unknown1.Get()); - TestAssert::AreEqual(1, base1->GetValue1()); - IBaseSample2* base2 = query_cast(base1); - TestAssert::AreEqual(2, base2->GetValue2()); - IBaseSample3* base3 = query_cast(base1); - TestAssert::IsNull(base3); - UnknownSample6* unknown2 = query_cast(base2); - OACR_USE_PTR(unknown2); // We do not want to make unknown2 const in this test. - TestAssert::AreEqual(2, unknown2->GetValue2()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_WeakRefCount_query_cast_ptr) + { + bool deleted = false; + { + // UnknownSample6 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + IBaseSample1* base1 = query_cast(unknown1.Get()); + TestAssert::AreEqual(1, base1->GetValue1()); + IBaseSample2* base2 = query_cast(base1); + TestAssert::AreEqual(2, base2->GetValue2()); + IBaseSample3* base3 = query_cast(base1); + TestAssert::IsNull(base3); + UnknownSample6* unknown2 = query_cast(base2); + OACR_USE_PTR(unknown2); // We do not want to make unknown2 const in this test. + TestAssert::AreEqual(2, unknown2->GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_WeakRefCount_query_cast_ref) - { - bool deleted = false; - { - // UnknownSample6 implements IBaseSample1, IBaseSample2, and not IBaseSample3 - Mso::TCntPtr unknown1 = Mso::Make(/*ref*/deleted); - IBaseSample1& base1 = query_cast(*unknown1); - TestAssert::AreEqual(1, base1.GetValue1()); - IBaseSample2& base2 = query_cast(base1); - TestAssert::AreEqual(2, base2.GetValue2()); - TestAssert::ExpectVEC([&]() - { - query_cast(base1); - }); - UnknownSample6& unknown2 = query_cast(base2); - OACR_USE_PTR(&unknown2); // We do not want to make unknown2 const in this test. - TestAssert::AreEqual(2, unknown2.GetValue2()); - } - TestAssert::IsTrue(deleted); - } + TEST_METHOD(UnknownObject_WeakRefCount_query_cast_ref) + { + bool deleted = false; + { + // UnknownSample6 implements IBaseSample1, IBaseSample2, and not IBaseSample3 + Mso::TCntPtr unknown1 = Mso::Make(/*ref*/ deleted); + IBaseSample1& base1 = query_cast(*unknown1); + TestAssert::AreEqual(1, base1.GetValue1()); + IBaseSample2& base2 = query_cast(base1); + TestAssert::AreEqual(2, base2.GetValue2()); + TestAssert::ExpectVEC([&]() { query_cast(base1); }); + UnknownSample6& unknown2 = query_cast(base2); + OACR_USE_PTR(&unknown2); // We do not want to make unknown2 const in this test. + TestAssert::AreEqual(2, unknown2.GetValue2()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleUnknown_OneBaseInterface) - { - bool deleted = false; - { - SimpleUnknownSample1 unknown1(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1.GetValue1()); + TEST_METHOD(UnknownObject_SimpleUnknown_OneBaseInterface) + { + bool deleted = false; + { + SimpleUnknownSample1 unknown1(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1.GetValue1()); - const ISimpleUnknownSample1* base1 = &unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); - } - TestAssert::IsTrue(deleted); - } + const ISimpleUnknownSample1* base1 = &unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleUnknown_TwoBaseInterfaces) - { - bool deleted = false; - { - SimpleUnknownSample2 unknown1(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1.GetValue1()); + TEST_METHOD(UnknownObject_SimpleUnknown_TwoBaseInterfaces) + { + bool deleted = false; + { + SimpleUnknownSample2 unknown1(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1.GetValue1()); - const ISimpleUnknownSample1* base1 = &unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); + const ISimpleUnknownSample1* base1 = &unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); - const ISimpleUnknownSample2* base2 = simpleqi_cast(base1); - TestAssert::AreEqual(2, base2->GetValue2()); + const ISimpleUnknownSample2* base2 = simpleqi_cast(base1); + TestAssert::AreEqual(2, base2->GetValue2()); - const ISimpleUnknownSample1* base11 = simpleqi_cast(base2); - TestAssert::AreEqual(1, base11->GetValue1()); + const ISimpleUnknownSample1* base11 = simpleqi_cast(base2); + TestAssert::AreEqual(1, base11->GetValue1()); - const ISimpleUnknownSample3* base3 = simpleqi_cast(base2); - TestAssert::IsNull(base3); - } - TestAssert::IsTrue(deleted); - } + const ISimpleUnknownSample3* base3 = simpleqi_cast(base2); + TestAssert::IsNull(base3); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleUnknown_TwoBaseInterfaces_Unique_ptr) - { - bool deleted = false; - { - std::unique_ptr unknown1 = std::make_unique(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); + TEST_METHOD(UnknownObject_SimpleUnknown_TwoBaseInterfaces_Unique_ptr) + { + bool deleted = false; + { + std::unique_ptr unknown1 = std::make_unique(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); - const ISimpleUnknownSample1* base1 = unknown1.get(); - TestAssert::AreEqual(1, base1->GetValue1()); + const ISimpleUnknownSample1* base1 = unknown1.get(); + TestAssert::AreEqual(1, base1->GetValue1()); - const ISimpleUnknownSample2* base2 = simpleqi_cast(base1); - TestAssert::AreEqual(2, base2->GetValue2()); + const ISimpleUnknownSample2* base2 = simpleqi_cast(base1); + TestAssert::AreEqual(2, base2->GetValue2()); - const ISimpleUnknownSample1* base11 = simpleqi_cast(base2); - TestAssert::AreEqual(1, base11->GetValue1()); + const ISimpleUnknownSample1* base11 = simpleqi_cast(base2); + TestAssert::AreEqual(1, base11->GetValue1()); - const ISimpleUnknownSample3* base3 = simpleqi_cast(base2); - TestAssert::IsNull(base3); - } - TestAssert::IsTrue(deleted); - } + const ISimpleUnknownSample3* base3 = simpleqi_cast(base2); + TestAssert::IsNull(base3); + } + TestAssert::IsTrue(deleted); + } - TEST_METHOD(UnknownObject_SimpleUnknown_Derived) - { - bool deleted = false; - { - SimpleUnknownSample3 unknown1(/*ref*/deleted); - TestAssert::AreEqual(1, unknown1.GetValue1()); + TEST_METHOD(UnknownObject_SimpleUnknown_Derived) + { + bool deleted = false; + { + SimpleUnknownSample3 unknown1(/*ref*/ deleted); + TestAssert::AreEqual(1, unknown1.GetValue1()); - const ISimpleUnknownSample1* base1 = &unknown1; - TestAssert::AreEqual(1, base1->GetValue1()); + const ISimpleUnknownSample1* base1 = &unknown1; + TestAssert::AreEqual(1, base1->GetValue1()); - const ISimpleUnknownSample2* base2 = simpleqi_cast(base1); - TestAssert::AreEqual(2, base2->GetValue2()); + const ISimpleUnknownSample2* base2 = simpleqi_cast(base1); + TestAssert::AreEqual(2, base2->GetValue2()); - const ISimpleUnknownSample1* base11 = simpleqi_cast(base2); - TestAssert::AreEqual(1, base11->GetValue1()); + const ISimpleUnknownSample1* base11 = simpleqi_cast(base2); + TestAssert::AreEqual(1, base11->GetValue1()); - const ISimpleUnknownSample3* base3 = simpleqi_cast(base2); - TestAssert::IsNull(base3); + const ISimpleUnknownSample3* base3 = simpleqi_cast(base2); + TestAssert::IsNull(base3); - const ISimpleUnknownSample21* base21 = simpleqi_cast(base1); - TestAssert::AreEqual(21, base21->GetValue21()); - } - TestAssert::IsTrue(deleted); - } + const ISimpleUnknownSample21* base21 = simpleqi_cast(base1); + TestAssert::AreEqual(21, base21->GetValue21()); + } + TestAssert::IsTrue(deleted); + } #if defined(DEBUG) && defined(TEST_BAD_INHERITANCE1) - TEST_METHOD(UnknownObject_BadInheritance1) - { - TestAssert::ExpectVEC([&]() noexcept - { - // This code must not compile, but if we remove the static assert from ObjectRefCount.h then we must have VEC here. - // You will see a memory leak here because we cannot destroy object correctly. - Mso::Make(); - }); - } + TEST_METHOD(UnknownObject_BadInheritance1) + { + TestAssert::ExpectVEC([&]() noexcept { + // This code must not compile, but if we remove the static assert from ObjectRefCount.h then we must have VEC + // here. You will see a memory leak here because we cannot destroy object correctly. + Mso::Make(); + }); + } #endif #if defined(DEBUG) && defined(TEST_BAD_INHERITANCE2) - TEST_METHOD(UnknownObject_BadInheritance2) - { - TestAssert::ExpectVEC([&]() noexcept - { - // You will see a memory leak here because we cannot destroy object correctly. - Mso::Make(); - }); - } + TEST_METHOD(UnknownObject_BadInheritance2) + { + TestAssert::ExpectVEC([&]() noexcept { + // You will see a memory leak here because we cannot destroy object correctly. + Mso::Make(); + }); + } #endif - TEST_METHOD(UnknownObject_MyMemHeap_SimpleRefCount) - { - bool deleted = false; - bool allocCalled = false; - bool freeCalled = false; - { - MyMemHeap memHeap(/*ref*/allocCalled, /*ref*/freeCalled); - Mso::TCntPtr unknown1 = Mso::MakeAlloc(&memHeap, /*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(allocCalled); - TestAssert::IsTrue(freeCalled); - } + TEST_METHOD(UnknownObject_MyMemHeap_SimpleRefCount) + { + bool deleted = false; + bool allocCalled = false; + bool freeCalled = false; + { + MyMemHeap memHeap(/*ref*/ allocCalled, /*ref*/ freeCalled); + Mso::TCntPtr unknown1 = + Mso::MakeAlloc(&memHeap, /*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(allocCalled); + TestAssert::IsTrue(freeCalled); + } - TEST_METHOD(UnknownObject_MyMemHeap_WeakRefCount) - { - bool deleted = false; - bool allocCalled = false; - bool freeCalled = false; - { - MyMemHeap memHeap(/*ref*/allocCalled, /*ref*/freeCalled); - Mso::TCntPtr unknown1 = Mso::MakeAlloc(&memHeap, /*ref*/deleted); - TestAssert::AreEqual(1, unknown1->GetValue1()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(allocCalled); - TestAssert::IsTrue(freeCalled); - } + TEST_METHOD(UnknownObject_MyMemHeap_WeakRefCount) + { + bool deleted = false; + bool allocCalled = false; + bool freeCalled = false; + { + MyMemHeap memHeap(/*ref*/ allocCalled, /*ref*/ freeCalled); + Mso::TCntPtr unknown1 = + Mso::MakeAlloc(&memHeap, /*ref*/ deleted); + TestAssert::AreEqual(1, unknown1->GetValue1()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(allocCalled); + TestAssert::IsTrue(freeCalled); + } }; diff --git a/libs/object/tests/weakPtrTest.cpp b/libs/object/tests/weakPtrTest.cpp index 8cc07fb..a4f7b5b 100644 --- a/libs/object/tests/weakPtrTest.cpp +++ b/libs/object/tests/weakPtrTest.cpp @@ -13,866 +13,854 @@ Unit tests for classes in the ObjectWeakPtr.h struct DECLSPEC_NOVTABLE IWeakPtrSample1 : public Mso::IRefCounted { - virtual int GetValue1() = 0; + virtual int GetValue1() = 0; }; struct DECLSPEC_NOVTABLE IWeakPtrSample2 : public Mso::IRefCounted { - virtual int GetValue2() = 0; + virtual int GetValue2() = 0; }; struct DECLSPEC_NOVTABLE IWeakPtrSample3 : public Mso::IWeakRefCounted { - virtual int GetValue3() = 0; + virtual int GetValue3() = 0; }; class WeakPtrSample1 final - : public Mso::RefCountedObject + : public Mso::RefCountedObject { public: - WeakPtrSample1(bool& deleted) noexcept - : m_deleted(deleted) - { - } + WeakPtrSample1(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue1() noexcept override - { - return 1; - } + virtual int GetValue1() noexcept override + { + return 1; + } - virtual int GetValue2() noexcept override - { - return 2; - } + virtual int GetValue2() noexcept override + { + return 2; + } - std::function PassThisToLambda() - { - Mso::WeakPtr weakThis(this); - auto lambda = [weakThis]() - { - auto strongThis = weakThis.GetStrongPtr(); - TestAssert::IsNotNull(strongThis.Get(), L"Cannot get StrongPtr"); - }; + std::function PassThisToLambda() + { + Mso::WeakPtr weakThis(this); + auto lambda = [weakThis]() { + auto strongThis = weakThis.GetStrongPtr(); + TestAssert::IsNotNull(strongThis.Get(), L"Cannot get StrongPtr"); + }; - return lambda; // causes an extra copy of lambda. - } + return lambda; // causes an extra copy of lambda. + } protected: - virtual ~WeakPtrSample1() noexcept - { - m_deleted = true; - } + virtual ~WeakPtrSample1() noexcept + { + m_deleted = true; + } private: - bool& m_deleted; + bool& m_deleted; }; -class WeakPtrSample3 final - : public Mso::RefCountedObject +class WeakPtrSample3 final : public Mso::RefCountedObject { public: - WeakPtrSample3(bool& deleted) noexcept - : m_deleted(deleted) - { - } + WeakPtrSample3(bool& deleted) noexcept : m_deleted(deleted) {} - virtual int GetValue3() noexcept override - { - return 3; - } + virtual int GetValue3() noexcept override + { + return 3; + } private: - virtual ~WeakPtrSample3() noexcept - { - m_deleted = true; - } + virtual ~WeakPtrSample3() noexcept + { + m_deleted = true; + } - bool& m_deleted; + bool& m_deleted; }; TestClassComponent(ObjectWeakPtrTest, Mso.ObjectWeakPtr) -TEST_CLASS(ObjectWeakPtrTest) + TEST_CLASS (ObjectWeakPtrTest){TEST_METHOD(WeakPtr_Default){Mso::WeakPtr weakPtr; + +TestAssert::IsTrue(weakPtr.IsExpired()); +TestAssert::IsNull(weakPtr.GetStrongPtr().Get(), L"Expected null"); +} + +TEST_METHOD(WeakPtr_Null) { - TEST_METHOD(WeakPtr_Default) - { - Mso::WeakPtr weakPtr; - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get(), L"Expected null"); - } - - TEST_METHOD(WeakPtr_Null) - { - Mso::WeakPtr weakPtr = nullptr; - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get(), L"Expected null"); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_PointerAndWeakRef1) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr.Get(), &ptr->GetWeakRef()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_PointerAndWeakRef21) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr.Get(), &ptr->GetWeakRef()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - // IWeakPtrSample2 is the second in the inheritance chain and we need to make sure void* casting in Mso::WeakPtr works. - TEST_METHOD(WeakPtr_PointerAndWeakRef22) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - - Mso::WeakPtr weakPtr1(ptr.Get()); - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr1.GetStrongPtr().Get()); - - Mso::WeakPtr weakPtr2(ptr.Get(), &ptr->GetWeakRef()); - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a IWeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_PointerAndWeakRef3) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(static_cast(ptr.Get()), &ptr->GetWeakRef()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_NullPointerAndWeakRef) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - WeakPtrSample1* ptrNull = nullptr; - Mso::WeakPtr weakPtr(ptrNull, &ptr->GetWeakRef()); - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_Pointer1) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr.Get()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_Pointer2) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr.Get()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_NullPointer) - { - WeakPtrSample1* ptrNull = nullptr; - Mso::WeakPtr weakPtr(ptrNull); - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAndWeakRef1) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr, &ptr->GetWeakRef()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Mso::TCntPtr is assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAndWeakRef21) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr, &ptr->GetWeakRef()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Mso::TCntPtr is assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAndWeakRef22) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - - Mso::WeakPtr weakPtr1(ptr); - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr1.GetStrongPtr().Get()); - - Mso::WeakPtr weakPtr2(ptr, &ptr->GetWeakRef()); - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a IWeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAndWeakRef3) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(static_cast(ptr), &ptr->GetWeakRef()); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_NullTCntPtrAndWeakRef) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::TCntPtr ptrNull = nullptr; - Mso::WeakPtr weakPtr(ptrNull, &ptr->GetWeakRef()); - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtr1) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtr2) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr(ptr); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_NullTCntPtr) - { - Mso::TCntPtr ptrNull = nullptr; - Mso::WeakPtr weakPtr(ptrNull); - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_CopyConstructor) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - Mso::WeakPtr weakPtr2(weakPtr1); - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_CopyConstructorInterface) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - Mso::WeakPtr weakPtr2(weakPtr1); - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_CopyConstructorInterface2) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - Mso::WeakPtr weakPtr2(weakPtr1); - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_MoveConstructor) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - Mso::WeakPtr weakPtr2(std::move(weakPtr1)); - - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_MoveConstructorInterface) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - Mso::WeakPtr weakPtr2(std::move(weakPtr1)); - - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_MoveConstructorInterface2) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - Mso::WeakPtr weakPtr2(std::move(weakPtr1)); - - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_NullAssignment) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - - weakPtr1 = nullptr; - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_PointerAssignment1) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptr.Get(); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_PointerAssignment21) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptr.Get(); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_PointerAssignment22) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptr.Get(); - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_NullPointerAssignment) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - WeakPtrSample1* ptrNull = nullptr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptrNull; - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // TCntPtr with a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAssignment1) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptr; - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // TCntPtr with a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAssignment21) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptr; - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // TCntPtr with a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_TCntPtrAssignment22) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptr; - - TestAssert::IsFalse(weakPtr.IsExpired()); - TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - // TCntPtr with a Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr - TEST_METHOD(WeakPtr_NullTCntPtrAssignment) - { - bool deleted = false; - { - Mso::WeakPtr weakPtr; - Mso::TCntPtr ptrNull = nullptr; - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - weakPtr = ptrNull; - - TestAssert::IsTrue(weakPtr.IsExpired()); - TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_CopyAssignment) - { - Mso::WeakPtr weakPtr2; - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - weakPtr2 = weakPtr1; - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr2.IsExpired()); - TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_CopyAssignmentInterface) - { - Mso::WeakPtr weakPtr2; - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - weakPtr2 = weakPtr1; - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr2.IsExpired()); - TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_CopyAssignmentInterface2) - { - Mso::WeakPtr weakPtr2; - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - weakPtr2 = weakPtr1; - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr2.IsExpired()); - TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_CopyAssignmentSamePtr) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - - OACR_WARNING_SUPPRESS(IDENTITY_ASSIGNMENT, "We want to test our code that nothing bad happens in this case"); - weakPtr1 = weakPtr1; - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_MoveAssignment) - { - Mso::WeakPtr weakPtr2; - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - weakPtr2 = std::move(weakPtr1); - - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr2.IsExpired()); - TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_MoveAssignmentInterface) - { - Mso::WeakPtr weakPtr2; - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - weakPtr2 = std::move(weakPtr1); - - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr2.IsExpired()); - TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_MoveAssignmentInterface2) - { - Mso::WeakPtr weakPtr2; - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - weakPtr2 = std::move(weakPtr1); - - TestAssert::IsTrue(weakPtr1.IsExpired()); - TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); - - TestAssert::IsFalse(weakPtr2.IsExpired()); - TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); - TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - TestAssert::IsTrue(weakPtr2.IsExpired()); - TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); - } - - TEST_METHOD(WeakPtr_MoveAssignmentSamePtr) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr); - - weakPtr1 = std::move(weakPtr1); - - TestAssert::IsFalse(weakPtr1.IsExpired()); - TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); - TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_PassToLambda) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/*ref*/deleted); - auto func = ptr->PassThisToLambda(); - func(); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_IsEmptyOnDefaultConstructedObject) - { - Mso::WeakPtr weakPtr; - TestAssert::IsTrue(weakPtr.IsEmpty()); - } - - TEST_METHOD(WeakPtr_IsEmptyOnObjectConstructedWithNullptrArg) - { - Mso::WeakPtr weakPtr = nullptr; - TestAssert::IsTrue(weakPtr.IsEmpty()); - } - - TEST_METHOD(WeakPtr_IsEmptyOnObjectConstructedWithNonNullArg) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/* ref */ deleted); - Mso::WeakPtr weakPtr = ptr; - TestAssert::IsFalse(weakPtr.IsEmpty()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_IsEmptyOnExpiredObject) - { - bool deleted = false; - { - Mso::TCntPtr ptr = Mso::Make(/* ref */ deleted); - Mso::WeakPtr weakPtr = ptr; - TestAssert::IsFalse(weakPtr.IsEmpty()); - TestAssert::IsFalse(weakPtr.IsExpired()); - - // cause the object to expire - ptr.Clear(); - - TestAssert::IsFalse(weakPtr.IsEmpty()); - TestAssert::IsTrue(weakPtr.IsExpired()); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_EqualityOperator) - { - bool deleted = false; - { - Mso::TCntPtr ptr1 = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr1); - - Mso::WeakPtr weakPtr2 = weakPtr1; - - Mso::WeakPtr weakPtr3 = nullptr; - - TestAssert::IsTrue(weakPtr1 == weakPtr2); - TestAssert::IsTrue(weakPtr3 == nullptr); - TestAssert::IsTrue(nullptr == weakPtr3); - TestAssert::IsTrue(weakPtr1 != weakPtr3); - TestAssert::IsTrue(weakPtr2 != nullptr); - TestAssert::IsTrue(nullptr != weakPtr2); - } - TestAssert::IsTrue(deleted); - } - - TEST_METHOD(WeakPtr_CanConvertFromTCntPtrToIWeakRefCounted) - { - bool deleted = false; - { - // convert TCntPtr to IWeakRefCounted-derived interface to WeakPtr to that interface - Mso::TCntPtr ptr1 = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1(ptr1); - TestAssert::IsFalse(weakPtr1.IsEmpty()); - TestAssert::IsFalse(weakPtr1.IsExpired()); - - // transfer the strong reference from ptr1 to ptr2 using weakPtr1 - Mso::TCntPtr ptr2 = weakPtr1.GetStrongPtr(); - ptr1 = nullptr; - TestAssert::IsFalse(weakPtr1.IsEmpty()); - TestAssert::IsFalse(weakPtr1.IsExpired()); - - // nullify the strong reference: weak ptr expires but remains non-empty - ptr2 = nullptr; - TestAssert::IsFalse(weakPtr1.IsEmpty()); - TestAssert::IsTrue(weakPtr1.IsExpired()); - } - TestAssert::IsTrue(deleted); - } - - TESTMETHOD_REQUIRES_SEH(WeakPtr_CannotConvertFromTCntPtrToIRefCounted) - { - bool deleted = false; - { - Mso::TCntPtr ptr1 = Mso::Make(/*ref*/deleted); - Mso::WeakPtr weakPtr1; - TestAssert::ExpectVEC([&]() noexcept - { - weakPtr1 = ptr1; // tag_bad22 is expected here - }); - } - TestAssert::IsTrue(deleted); - } -}; + Mso::WeakPtr weakPtr = nullptr; + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get(), L"Expected null"); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_PointerAndWeakRef1) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr.Get(), &ptr->GetWeakRef()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_PointerAndWeakRef21) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr.Get(), &ptr->GetWeakRef()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +// IWeakPtrSample2 is the second in the inheritance chain and we need to make sure void* casting in Mso::WeakPtr works. +TEST_METHOD(WeakPtr_PointerAndWeakRef22) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + + Mso::WeakPtr weakPtr1(ptr.Get()); + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr1.GetStrongPtr().Get()); + + Mso::WeakPtr weakPtr2(ptr.Get(), &ptr->GetWeakRef()); + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a IWeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_PointerAndWeakRef3) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(static_cast(ptr.Get()), &ptr->GetWeakRef()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_NullPointerAndWeakRef) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + WeakPtrSample1* ptrNull = nullptr; + Mso::WeakPtr weakPtr(ptrNull, &ptr->GetWeakRef()); + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_Pointer1) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr.Get()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_Pointer2) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr.Get()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_NullPointer) +{ + WeakPtrSample1* ptrNull = nullptr; + Mso::WeakPtr weakPtr(ptrNull); + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAndWeakRef1) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr, &ptr->GetWeakRef()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Mso::TCntPtr is assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAndWeakRef21) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr, &ptr->GetWeakRef()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Mso::TCntPtr is assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAndWeakRef22) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + + Mso::WeakPtr weakPtr1(ptr); + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr1.GetStrongPtr().Get()); + + Mso::WeakPtr weakPtr2(ptr, &ptr->GetWeakRef()); + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a IWeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAndWeakRef3) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(static_cast(ptr), &ptr->GetWeakRef()); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_NullTCntPtrAndWeakRef) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::TCntPtr ptrNull = nullptr; + Mso::WeakPtr weakPtr(ptrNull, &ptr->GetWeakRef()); + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtr1) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtr2) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr(ptr); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_NullTCntPtr) +{ + Mso::TCntPtr ptrNull = nullptr; + Mso::WeakPtr weakPtr(ptrNull); + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_CopyConstructor) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + Mso::WeakPtr weakPtr2(weakPtr1); + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_CopyConstructorInterface) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + Mso::WeakPtr weakPtr2(weakPtr1); + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_CopyConstructorInterface2) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + Mso::WeakPtr weakPtr2(weakPtr1); + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_MoveConstructor) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + Mso::WeakPtr weakPtr2(std::move(weakPtr1)); + + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_MoveConstructorInterface) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + Mso::WeakPtr weakPtr2(std::move(weakPtr1)); + + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_MoveConstructorInterface2) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + Mso::WeakPtr weakPtr2(std::move(weakPtr1)); + + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_NullAssignment) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + + weakPtr1 = nullptr; + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_PointerAssignment1) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptr.Get(); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_PointerAssignment21) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptr.Get(); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_PointerAssignment22) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptr.Get(); + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_NullPointerAssignment) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + WeakPtrSample1* ptrNull = nullptr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptrNull; + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// TCntPtr with a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAssignment1) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptr; + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// TCntPtr with a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAssignment21) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptr; + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// TCntPtr with a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_TCntPtrAssignment22) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptr; + + TestAssert::IsFalse(weakPtr.IsExpired()); + TestAssert::IsNotNull(weakPtr.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +// TCntPtr with a Null pointer to a WeakPtrSample1 assigned to Mso::WeakPtr +TEST_METHOD(WeakPtr_NullTCntPtrAssignment) +{ + bool deleted = false; + { + Mso::WeakPtr weakPtr; + Mso::TCntPtr ptrNull = nullptr; + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + weakPtr = ptrNull; + + TestAssert::IsTrue(weakPtr.IsExpired()); + TestAssert::IsNull(weakPtr.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_CopyAssignment) +{ + Mso::WeakPtr weakPtr2; + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + weakPtr2 = weakPtr1; + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr2.IsExpired()); + TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_CopyAssignmentInterface) +{ + Mso::WeakPtr weakPtr2; + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + weakPtr2 = weakPtr1; + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr2.IsExpired()); + TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_CopyAssignmentInterface2) +{ + Mso::WeakPtr weakPtr2; + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + weakPtr2 = weakPtr1; + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr2.IsExpired()); + TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_CopyAssignmentSamePtr) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + + OACR_WARNING_SUPPRESS(IDENTITY_ASSIGNMENT, "We want to test our code that nothing bad happens in this case"); + weakPtr1 = weakPtr1; + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_MoveAssignment) +{ + Mso::WeakPtr weakPtr2; + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + weakPtr2 = std::move(weakPtr1); + + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr2.IsExpired()); + TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_MoveAssignmentInterface) +{ + Mso::WeakPtr weakPtr2; + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + weakPtr2 = std::move(weakPtr1); + + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr2.IsExpired()); + TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_MoveAssignmentInterface2) +{ + Mso::WeakPtr weakPtr2; + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + weakPtr2 = std::move(weakPtr1); + + TestAssert::IsTrue(weakPtr1.IsExpired()); + TestAssert::IsNull(weakPtr1.GetStrongPtr().Get()); + + TestAssert::IsFalse(weakPtr2.IsExpired()); + TestAssert::IsNotNull(weakPtr2.GetStrongPtr().Get()); + TestAssert::IsTrue(static_cast(ptr.Get()) == weakPtr2.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); + TestAssert::IsTrue(weakPtr2.IsExpired()); + TestAssert::IsNull(weakPtr2.GetStrongPtr().Get()); +} + +TEST_METHOD(WeakPtr_MoveAssignmentSamePtr) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr); + + weakPtr1 = std::move(weakPtr1); + + TestAssert::IsFalse(weakPtr1.IsExpired()); + TestAssert::IsNotNull(weakPtr1.GetStrongPtr().Get()); + TestAssert::IsTrue(ptr.Get() == weakPtr1.GetStrongPtr().Get()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_PassToLambda) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/*ref*/ deleted); + auto func = ptr->PassThisToLambda(); + func(); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_IsEmptyOnDefaultConstructedObject) +{ + Mso::WeakPtr weakPtr; + TestAssert::IsTrue(weakPtr.IsEmpty()); +} + +TEST_METHOD(WeakPtr_IsEmptyOnObjectConstructedWithNullptrArg) +{ + Mso::WeakPtr weakPtr = nullptr; + TestAssert::IsTrue(weakPtr.IsEmpty()); +} + +TEST_METHOD(WeakPtr_IsEmptyOnObjectConstructedWithNonNullArg) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/* ref */ deleted); + Mso::WeakPtr weakPtr = ptr; + TestAssert::IsFalse(weakPtr.IsEmpty()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_IsEmptyOnExpiredObject) +{ + bool deleted = false; + { + Mso::TCntPtr ptr = Mso::Make(/* ref */ deleted); + Mso::WeakPtr weakPtr = ptr; + TestAssert::IsFalse(weakPtr.IsEmpty()); + TestAssert::IsFalse(weakPtr.IsExpired()); + + // cause the object to expire + ptr.Clear(); + + TestAssert::IsFalse(weakPtr.IsEmpty()); + TestAssert::IsTrue(weakPtr.IsExpired()); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_EqualityOperator) +{ + bool deleted = false; + { + Mso::TCntPtr ptr1 = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr1); + + Mso::WeakPtr weakPtr2 = weakPtr1; + + Mso::WeakPtr weakPtr3 = nullptr; + + TestAssert::IsTrue(weakPtr1 == weakPtr2); + TestAssert::IsTrue(weakPtr3 == nullptr); + TestAssert::IsTrue(nullptr == weakPtr3); + TestAssert::IsTrue(weakPtr1 != weakPtr3); + TestAssert::IsTrue(weakPtr2 != nullptr); + TestAssert::IsTrue(nullptr != weakPtr2); + } + TestAssert::IsTrue(deleted); +} + +TEST_METHOD(WeakPtr_CanConvertFromTCntPtrToIWeakRefCounted) +{ + bool deleted = false; + { + // convert TCntPtr to IWeakRefCounted-derived interface to WeakPtr to that interface + Mso::TCntPtr ptr1 = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1(ptr1); + TestAssert::IsFalse(weakPtr1.IsEmpty()); + TestAssert::IsFalse(weakPtr1.IsExpired()); + + // transfer the strong reference from ptr1 to ptr2 using weakPtr1 + Mso::TCntPtr ptr2 = weakPtr1.GetStrongPtr(); + ptr1 = nullptr; + TestAssert::IsFalse(weakPtr1.IsEmpty()); + TestAssert::IsFalse(weakPtr1.IsExpired()); + + // nullify the strong reference: weak ptr expires but remains non-empty + ptr2 = nullptr; + TestAssert::IsFalse(weakPtr1.IsEmpty()); + TestAssert::IsTrue(weakPtr1.IsExpired()); + } + TestAssert::IsTrue(deleted); +} + +TESTMETHOD_REQUIRES_SEH(WeakPtr_CannotConvertFromTCntPtrToIRefCounted) +{ + bool deleted = false; + { + Mso::TCntPtr ptr1 = Mso::Make(/*ref*/ deleted); + Mso::WeakPtr weakPtr1; + TestAssert::ExpectVEC([&]() noexcept { + weakPtr1 = ptr1; // tag_bad22 is expected here + }); + } + TestAssert::IsTrue(deleted); +} +} +; diff --git a/libs/platformAdapters/include/object/IUnknownShim.h b/libs/platformAdapters/include/object/IUnknownShim.h index e9c49bc..67e3ff1 100644 --- a/libs/platformAdapters/include/object/IUnknownShim.h +++ b/libs/platformAdapters/include/object/IUnknownShim.h @@ -27,7 +27,8 @@ MSO_STRUCT_GUID(IUnknown, "00000000-0000-0000-C000-000000000046") #define FACILITY_WIN32 7 -#define __HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) +#define __HRESULT_FROM_WIN32(x) \ + ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT)(((x)&0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) #define HRESULT_FROM_WIN32(x) __HRESULT_FROM_WIN32(x) #ifndef __LP64__ @@ -36,18 +37,18 @@ typedef long HRESULT; typedef int HRESULT; #endif #ifndef __GNUC__ -#define STDMETHODCALLTYPE __stdcall +#define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif -#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method -#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method -#define STDMETHODIMP HRESULT STDMETHODCALLTYPE -#define STDMETHODIMP_(type) type STDMETHODCALLTYPE -#define STDMETHODIMPNOTHROW COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE -#define STDMETHODIMPNOTHROW_(type) COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE +#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method +#define STDMETHOD_(type, method) virtual type STDMETHODCALLTYPE method +#define STDMETHODIMP HRESULT STDMETHODCALLTYPE +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMPNOTHROW COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE +#define STDMETHODIMPNOTHROW_(type) COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE -#define S_OK ((HRESULT)0L) +#define S_OK ((HRESULT)0L) #define S_FALSE ((HRESULT)1L) #define ERROR_INSUFFICIENT_BUFFER 122L @@ -82,9 +83,9 @@ MSO_STRUCT_GUID(IUnknown, "00000000-0000-0000-C000-000000000046") #endif struct IUnknown { - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) = 0; - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) = 0; + virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; + virtual ULONG STDMETHODCALLTYPE Release(void) = 0; }; #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) diff --git a/libs/platformAdapters/include/platformAdapters/msoGuid.h b/libs/platformAdapters/include/platformAdapters/msoGuid.h index 01bdaeb..4f39791 100644 --- a/libs/platformAdapters/include/platformAdapters/msoGuid.h +++ b/libs/platformAdapters/include/platformAdapters/msoGuid.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Support for multi-platform GUID implementation. + Support for multi-platform GUID implementation. */ #pragma once #ifndef LIBLET_PLATFORMADAPTERS_MSOGUID_H @@ -18,17 +18,17 @@ MSO_STRUCT_GUID or MSO_CLASS_GUID are used to associate a GUID with a type in platform independent way: - MSO_STRUCT_GUID(IMyInterface, "8665E4CE-50ED-4C12-A96D-13BD1432C219") - struct DECLSPEC_NOVTABLE IMyInterface : IBaseInterface - { - virtual ReturnType1 Method1() = 0; - virtual ReturnType2 Method1(ArgType1 arg1) = 0; - }; + MSO_STRUCT_GUID(IMyInterface, "8665E4CE-50ED-4C12-A96D-13BD1432C219") + struct DECLSPEC_NOVTABLE IMyInterface : IBaseInterface + { + virtual ReturnType1 Method1() = 0; + virtual ReturnType2 Method1(ArgType1 arg1) = 0; + }; - MSO_CLASS_GUID(MyClass, "8665E4CE-50ED-4C12-A96D-13BD1432C219") - class MyClass : public IBaseInterface - { - }; + MSO_CLASS_GUID(MyClass, "8665E4CE-50ED-4C12-A96D-13BD1432C219") + class MyClass : public IBaseInterface + { + }; NOTE: GUID must not use curly braces around it. @@ -36,10 +36,10 @@ NOTE: GUID must not use curly braces around it. To retrieve GUID for a type use the __uuidof(): - const GUID& myTypeGuid = __uuidof(MyType); + const GUID& myTypeGuid = __uuidof(MyType); - template - T* qi_cast(TSource* s, const GUID& riid = __uuidof(T)); + template + T* qi_cast(TSource* s, const GUID& riid = __uuidof(T)); The __uuidof() is a Visual C++ specific operator that accepts a variety of inputs. @@ -50,12 +50,11 @@ This macro can only accept a type. We recommend to change code that uses an expr - Replace __uuidof(expr) with __uuidof_expr(expr) */ - /** ++ FAQ ++ Q: Why to use macro to associate a GUID with a type? -A: There is no C++ standard way to assign a GUID attribute to a type. Any solution that we provide at this point +A: There is no C++ standard way to assign a GUID attribute to a type. Any solution that we provide at this point is a workaround to this limitation. Macro can hide any such platform specific workarounds. Q: How does it work? @@ -63,7 +62,8 @@ A: For Visual C++ we use the __declspec(uuid) attribute. For Clang we use an overload of a function MsoGetGuid(T*). This function is used to initialize GuidOf::Value static field returned by __uuidof() macro. The main benefit of using function is that it allows us to associate GUID with a type in the type's namespace. - The function is discovered with help of C++ argument-dependent name lookup http://en.wikipedia.org/wiki/Argument_dependent_name_lookup . + The function is discovered with help of C++ argument-dependent name lookup +http://en.wikipedia.org/wiki/Argument_dependent_name_lookup . Q: Why not to use a template specialization for GUID association? A: This is what we tried first, but a template cannot be specialized in a different namespace. In our case we want to @@ -74,49 +74,51 @@ A: See the msoGuidDetails.h */ -namespace Mso -{ +namespace Mso { OACR_WARNING_PUSH OACR_WARNING_DISABLE(VAR_IN_HEADER, "False Positive for variable in header with template. (see Bug 1689514) ") /// To return false in TypeHasGuid::Value if type has no GUID defined by MSO_STRUCT_GUID/MSO_CLASS_GUID -template ::Mso::Details::GuidUtils::FalseType MsoTypeHasGuid(T*); +template +::Mso::Details::GuidUtils::FalseType MsoTypeHasGuid(T*); /// Type traits to check if type has a GUID defined by MSO_STRUCT_GUID/MSO_CLASS_GUID template struct TypeHasGuid { - typedef decltype(MsoTypeHasGuid(static_cast(nullptr))) Type; - enum { Value = Type::Value }; + typedef decltype(MsoTypeHasGuid(static_cast(nullptr))) Type; + enum + { + Value = Type::Value + }; }; - /** - This template is to address an issue with NDK linker which cannot properly compile - a template that uses a pointer to GUID as a template parameter. - E.g. the " struct TCntQIPtr " will fail to compile - because linker cannot find a static field which we use for __uuidof(T) implementation. - Instead, this line must be changed to " struct TCntQIPtr " - and we should use Mso::ResolveGuidPtr::Guid instead of piid inside of the template. - The Mso::ResolveGuidPtr has a specialization for nullptr that does all the "magic". + This template is to address an issue with NDK linker which cannot properly compile + a template that uses a pointer to GUID as a template parameter. + E.g. the " struct TCntQIPtr " will fail to compile + because linker cannot find a static field which we use for __uuidof(T) implementation. + Instead, this line must be changed to " struct TCntQIPtr " + and we should use Mso::ResolveGuidPtr::Guid instead of piid inside of the template. + The Mso::ResolveGuidPtr has a specialization for nullptr that does all the "magic". */ template struct ResolveGuidPtr { - static const GUID* Guid; + static const GUID* Guid; }; template const GUID* ResolveGuidPtr::Guid = guidPtr; template -struct ResolveGuidPtr(nullptr)> +struct ResolveGuidPtr(nullptr)> { - static const GUID* Guid; + static const GUID* Guid; }; template -const GUID* ResolveGuidPtr(nullptr)>::Guid = &__uuidof(T); +const GUID* ResolveGuidPtr(nullptr)>::Guid = &__uuidof(T); OACR_WARNING_POP } // namespace Mso diff --git a/libs/platformAdapters/include/platformAdapters/msoGuidDetails.h b/libs/platformAdapters/include/platformAdapters/msoGuidDetails.h index 35f7888..4e5ce6d 100644 --- a/libs/platformAdapters/include/platformAdapters/msoGuidDetails.h +++ b/libs/platformAdapters/include/platformAdapters/msoGuidDetails.h @@ -20,32 +20,36 @@ See the msoGuid.h for the usage guidelines. #include #if MS_TARGET_POSIX -# include +#include #endif // MS_TARGET_POSIX // Private macro for MSO_STRUCT_GUID/MSO_CLASS_GUID macro implementations. #if COMPILER_SUPPORTS_UUID // For Visual C++ -# define MSO_GUID_IMPL(keyword, type, guidString) \ - static_assert(sizeof(guidString) == 37, "GUID string must have the following format: \"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\""); \ - keyword __declspec(uuid(guidString)) type; \ - __pragma(warning(suppress:25352)) \ - extern "C++" ::Mso::Details::GuidUtils::TrueType MsoTypeHasGuid(type*); +#define MSO_GUID_IMPL(keyword, type, guidString) \ + static_assert( \ + sizeof(guidString) == 37, \ + "GUID string must have the following format: \"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\""); \ + keyword __declspec(uuid(guidString)) type; \ + __pragma(warning(suppress : 25352)) extern "C++" ::Mso::Details::GuidUtils::TrueType MsoTypeHasGuid(type*); #else // For Clang -# define MSO_GUID_IMPL(keyword, type, guidString) \ - keyword type; \ - extern "C++" inline constexpr GUID MsoGetGuid(type*) noexcept { return ::Mso::Details::GuidUtils::StringToGuid(guidString); } \ - extern "C++" ::Mso::Details::GuidUtils::TrueType MsoTypeHasGuid(type*); +#define MSO_GUID_IMPL(keyword, type, guidString) \ + keyword type; \ + extern "C++" inline constexpr GUID MsoGetGuid(type*) noexcept \ + { \ + return ::Mso::Details::GuidUtils::StringToGuid(guidString); \ + } \ + extern "C++" ::Mso::Details::GuidUtils::TrueType MsoTypeHasGuid(type*); #endif // COMPILER_SUPPORTS_UUID /// Associates type with a GUID. To be used before type declaration. #define MSO_STRUCT_GUID(type, guidString) MSO_GUID_IMPL(struct, type, guidString) -#define MSO_CLASS_GUID( type, guidString) MSO_GUID_IMPL(class, type, guidString) +#define MSO_CLASS_GUID(type, guidString) MSO_GUID_IMPL(class, type, guidString) #define MSO_GUID(type, guidString) MSO_STRUCT_GUID(type, guidString) //========================================================================================================================== // GUID token is a special type that can be used to define and access GUIDs using only header files. // For example, to define a GUID in a header file without declaring a type, you can write: -// +// // MSO_DEFINE_GUID_TOKEN(MyToken, "d807b970-b875-4491-a88e-99038236d60f") // // Then to access the GUID: @@ -74,29 +78,26 @@ See the msoGuid.h for the usage guidelines. // // Each alias will have its own unique GUID associated with it. // To get GUID of an alias: -// +// // const GUID& intGuid = __uuidof(MyIntTemplate::GuidType); // const GUID& floatGuid = __uuidof(MyFloatTemplate::GuidType); // /// Gets type from the GUID token. -#define MSO_GET_GUID_TOKEN_TYPE(guidToken) \ - guidToken##_GuidToken +#define MSO_GET_GUID_TOKEN_TYPE(guidToken) guidToken##_GuidToken -/// Defines a GUID token type. -#define MSO_DEFINE_GUID_TOKEN(guidToken, guidString) \ - MSO_STRUCT_GUID(MSO_GET_GUID_TOKEN_TYPE(guidToken), guidString) +/// Defines a GUID token type. +#define MSO_DEFINE_GUID_TOKEN(guidToken, guidString) MSO_STRUCT_GUID(MSO_GET_GUID_TOKEN_TYPE(guidToken), guidString) /// A macro to access GUID by a token defined by MSO_DEFINE_GUID_TOKEN -#define __uuidof_token(guidToken) \ - __uuidof(MSO_GET_GUID_TOKEN_TYPE(guidToken)) +#define __uuidof_token(guidToken) __uuidof(MSO_GET_GUID_TOKEN_TYPE(guidToken)) //========================================================================================================================== /// Replacement for the MIDL_INTERFACE based on MSO_STRUCT_GUID. To be used in MIDL generated files. #define MIDL_INTERFACE2(type, guidString) \ - MSO_STRUCT_GUID(type, guidString) \ - struct DECLSPEC_NOVTABLE + MSO_STRUCT_GUID(type, guidString) \ + struct DECLSPEC_NOVTABLE // __uuidof(type) implementation for Clang. In VC++ we use the native __uuidof() operator. #if !COMPILER_SUPPORTS_UUID @@ -105,64 +106,64 @@ See the msoGuid.h for the usage guidelines. #endif /// A macro to be used instead of __uuidof(expr). For types use __uuidof(type). E.g. __uuidof_expr(this). -#define __uuidof_expr(expr) \ - __uuidof(typename std::remove_pointer::type>::type) - +#define __uuidof_expr(expr) __uuidof(typename std::remove_pointer::type>::type) // We must explicitly set the C++ extern context for the MIDL generated files where it is set to "C". extern "C++" { -namespace Mso { namespace Details { namespace GuidUtils { - -// To indicate that type has or does not have GUID. We do not want to add dependency on "type_traits" -struct TrueType { enum { Value = true }; }; -struct FalseType { enum { Value = false }; }; + namespace Mso { namespace Details { namespace GuidUtils { + // To indicate that type has or does not have GUID. We do not want to add dependency on "type_traits" + struct TrueType + { + enum + { + Value = true + }; + }; + struct FalseType + { + enum + { + Value = false + }; + }; #if !COMPILER_SUPPORTS_UUID -/// Default implementation of the MsoGetGuid. It is used when we cannot find type specific implementation -/// provided by MSO_STRUCT_GUID/MSO_CLASS_GUID macro. -template -inline GUID MsoGetGuid(T*) noexcept -{ - static_assert(sizeof(T) == 0, "GUID is undefined for the type T"); - return {}; -} + /// Default implementation of the MsoGetGuid. It is used when we cannot find type specific implementation + /// provided by MSO_STRUCT_GUID/MSO_CLASS_GUID macro. + template + inline GUID MsoGetGuid(T*) noexcept + { + static_assert(sizeof(T) == 0, "GUID is undefined for the type T"); + return {}; + } -/// Statically associates a GUID with a type. It is used by __uuidof() macro implementation. -template -struct GuidOf -{ - static const GUID Value; -}; + /// Statically associates a GUID with a type. It is used by __uuidof() macro implementation. + template + struct GuidOf + { + static const GUID Value; + }; -template -const GUID GuidOf::Value = MsoGetGuid(static_cast(nullptr)); + template + const GUID GuidOf::Value = MsoGetGuid(static_cast(nullptr)); + /// To represent a GUID string without curly braces: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX" + typedef char GuidString[37]; -/// To represent a GUID string without curly braces: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX" -typedef char GuidString[37]; - -/// Converts a hexadecimal ASCII character to an unsigned char. -constexpr const unsigned char H2U[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; + /// Converts a hexadecimal ASCII character to an unsigned char. + constexpr const unsigned char H2U[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, + 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; #if __clang__ #pragma clang diagnostic push @@ -170,26 +171,24 @@ constexpr const unsigned char H2U[256] = { #pragma clang diagnostic ignored "-Wchar-subscripts" #endif // __clang__ -/// Converts string to a GUID at compile time. Expected format: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX" -constexpr GUID StringToGuid(const GuidString& g) noexcept -{ - return - { - static_cast((H2U[g[0]] << 28) | (H2U[g[1]] << 24) | (H2U[g[2]] << 20) | (H2U[g[3]] << 16) | (H2U[g[4]] << 12) | (H2U[g[5]] << 8) | (H2U[g[6]] << 4) | H2U[g[7]]), - static_cast((H2U[g[9]] << 12) | (H2U[g[10]] << 8) | (H2U[g[11]] << 4) | H2U[g[12]]), - static_cast((H2U[g[14]] << 12) | (H2U[g[15]] << 8) | (H2U[g[16]] << 4) | H2U[g[17]]), - { - static_cast((H2U[g[19]] << 4) | H2U[g[20]]), - static_cast((H2U[g[21]] << 4) | H2U[g[22]]), - static_cast((H2U[g[24]] << 4) | H2U[g[25]]), - static_cast((H2U[g[26]] << 4) | H2U[g[27]]), - static_cast((H2U[g[28]] << 4) | H2U[g[29]]), - static_cast((H2U[g[30]] << 4) | H2U[g[31]]), - static_cast((H2U[g[32]] << 4) | H2U[g[33]]), - static_cast((H2U[g[34]] << 4) | H2U[g[35]]) - } - }; -} + /// Converts string to a GUID at compile time. Expected format: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX" + constexpr GUID StringToGuid(const GuidString& g) noexcept + { + return { + static_cast( + (H2U[g[0]] << 28) | (H2U[g[1]] << 24) | (H2U[g[2]] << 20) | (H2U[g[3]] << 16) | (H2U[g[4]] << 12) + | (H2U[g[5]] << 8) | (H2U[g[6]] << 4) | H2U[g[7]]), + static_cast((H2U[g[9]] << 12) | (H2U[g[10]] << 8) | (H2U[g[11]] << 4) | H2U[g[12]]), + static_cast((H2U[g[14]] << 12) | (H2U[g[15]] << 8) | (H2U[g[16]] << 4) | H2U[g[17]]), + {static_cast((H2U[g[19]] << 4) | H2U[g[20]]), + static_cast((H2U[g[21]] << 4) | H2U[g[22]]), + static_cast((H2U[g[24]] << 4) | H2U[g[25]]), + static_cast((H2U[g[26]] << 4) | H2U[g[27]]), + static_cast((H2U[g[28]] << 4) | H2U[g[29]]), + static_cast((H2U[g[30]] << 4) | H2U[g[31]]), + static_cast((H2U[g[32]] << 4) | H2U[g[33]]), + static_cast((H2U[g[34]] << 4) | H2U[g[35]])}}; + } #if __clang__ #pragma clang diagnostic pop @@ -197,7 +196,7 @@ constexpr GUID StringToGuid(const GuidString& g) noexcept #endif // !COMPILER_SUPPORTS_UUID -} } } // namespace Mso::Details::GuidUtils + }}} // namespace Mso::Details::GuidUtils } // extern "C++" #endif // LIBLET_PLATFORMADAPTERS_MSOGUIDDETAILS_H diff --git a/libs/platformAdapters/include/platformAdapters/types.h b/libs/platformAdapters/include/platformAdapters/types.h index fca739e..7680e98 100644 --- a/libs/platformAdapters/include/platformAdapters/types.h +++ b/libs/platformAdapters/include/platformAdapters/types.h @@ -19,7 +19,7 @@ #ifndef _BYTE_DEFINED #define _BYTE_DEFINED -typedef unsigned char BYTE;//__clang__ : conflict with libc++17 byte definition +typedef unsigned char BYTE; //__clang__ : conflict with libc++17 byte definition #endif // !_BYTE_DEFINED #ifndef _WORD_DEFINED @@ -39,7 +39,7 @@ typedef unsigned int UINT; #ifndef _LONG_DEFINED #define _LONG_DEFINED -typedef int32_t LONG; //MS_TARGET_APPLE LONG as a Windows type must stay 32-bit even in 64-bit code +typedef int32_t LONG; // MS_TARGET_APPLE LONG as a Windows type must stay 32-bit even in 64-bit code #endif // !_LONG_DEFINED #ifndef _ULONG_DEFINED @@ -49,7 +49,7 @@ typedef uint32_t ULONG; #ifndef _BOOL_DEFINED #define _BOOL_DEFINED -typedef int32_t BOOL; //MS_TARGET_APPLE +typedef int32_t BOOL; // MS_TARGET_APPLE #define TRUE 1 #define FALSE 0 #endif // !_BOOL_DEFINED @@ -71,7 +71,7 @@ typedef UINT_PTR WPARAM; #ifndef _DWORD_DEFINED #define _DWORD_DEFINED -typedef uint32_t DWORD; //MS_TARGET_APPLE DWORD as a Windows type must stay 32-bit even in 64-bit code +typedef uint32_t DWORD; // MS_TARGET_APPLE DWORD as a Windows type must stay 32-bit even in 64-bit code #endif // !_DWORD_DEFINED #ifndef _LPARAM_DEFINED diff --git a/libs/platformAdapters/include/platformAdapters/windowsFirst.h b/libs/platformAdapters/include/platformAdapters/windowsFirst.h index 8af31f8..2c704d5 100644 --- a/libs/platformAdapters/include/platformAdapters/windowsFirst.h +++ b/libs/platformAdapters/include/platformAdapters/windowsFirst.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Header to properly include windows.h + Header to properly include windows.h */ #pragma once #ifndef LIBLET_PLATFORMADAPTERS_WINDOWSFIRST_H diff --git a/libs/platform_posix/include/guiddef.h b/libs/platform_posix/include/guiddef.h index 2ada8be..1489a89 100644 --- a/libs/platform_posix/include/guiddef.h +++ b/libs/platform_posix/include/guiddef.h @@ -14,22 +14,24 @@ #ifndef GUID_DEFINED #define GUID_DEFINED #if defined(__midl) -typedef struct { - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - byte Data4[ 8 ]; +typedef struct +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + byte Data4[8]; } GUID; #else -typedef struct _GUID { +typedef struct _GUID +{ #ifdef __LP64__ - unsigned int Data1; + unsigned int Data1; #else - unsigned long Data1; + unsigned long Data1; #endif - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[ 8 ]; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; } GUID; #endif #endif @@ -44,10 +46,10 @@ typedef struct _GUID { #ifndef DECLSPEC_SELECTANY #if (_MSC_VER >= 1100) -#define DECLSPEC_SELECTANY __declspec(selectany) +#define DECLSPEC_SELECTANY __declspec(selectany) #else #if defined(__clang__) -#define DECLSPEC_SELECTANY __attribute__ ((weak)) +#define DECLSPEC_SELECTANY __attribute__((weak)) #else #define DECLSPEC_SELECTANY #endif @@ -56,9 +58,9 @@ typedef struct _GUID { #ifndef EXTERN_C #ifdef __cplusplus -#define EXTERN_C extern "C" +#define EXTERN_C extern "C" #else -#define EXTERN_C extern +#define EXTERN_C extern #endif #endif @@ -68,47 +70,45 @@ typedef struct _GUID { #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - EXTERN_C const GUID DECLSPEC_SELECTANY name \ - = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } + EXTERN_C const GUID DECLSPEC_SELECTANY name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}} #else -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - EXTERN_C const GUID FAR name +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) EXTERN_C const GUID FAR name #endif // INITGUID -#define DEFINE_OLEGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46) +#define DEFINE_OLEGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0, 0, 0, 0, 0, 0, 0, 0x46) #ifndef _GUIDDEF_H_ #define _GUIDDEF_H_ #ifndef __LPGUID_DEFINED__ #define __LPGUID_DEFINED__ -typedef GUID *LPGUID; +typedef GUID* LPGUID; #endif #ifndef __LPCGUID_DEFINED__ #define __LPCGUID_DEFINED__ -typedef const GUID *LPCGUID; +typedef const GUID* LPCGUID; #endif #ifndef __IID_DEFINED__ #define __IID_DEFINED__ #ifndef WIN32 -//EXTERN_C const GUID DECLSPEC_SELECTANY GUID_NULL +// EXTERN_C const GUID DECLSPEC_SELECTANY GUID_NULL // = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } }; #endif // WIN32 typedef GUID IID; -typedef IID *LPIID; -#define IID_NULL GUID_NULL +typedef IID* LPIID; +#define IID_NULL GUID_NULL #define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) typedef GUID CLSID; -typedef CLSID *LPCLSID; -#define CLSID_NULL GUID_NULL +typedef CLSID* LPCLSID; +#define CLSID_NULL GUID_NULL #define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) typedef GUID FMTID; -typedef FMTID *LPFMTID; -#define FMTID_NULL GUID_NULL +typedef FMTID* LPFMTID; +#define FMTID_NULL GUID_NULL #define IsEqualFMTID(rfmtid1, rfmtid2) IsEqualGUID(rfmtid1, rfmtid2) #ifdef __midl_proxy @@ -120,43 +120,43 @@ typedef FMTID *LPFMTID; #ifndef _REFGUID_DEFINED #define _REFGUID_DEFINED #ifdef __cplusplus -#define REFGUID const GUID & +#define REFGUID const GUID& #else -#define REFGUID const GUID * __MIDL_CONST +#define REFGUID const GUID* __MIDL_CONST #endif #endif #ifndef _REFIID_DEFINED #define _REFIID_DEFINED #ifdef __cplusplus -#define REFIID const IID & +#define REFIID const IID& #else -#define REFIID const IID * __MIDL_CONST +#define REFIID const IID* __MIDL_CONST #endif #endif #ifndef _REFCLSID_DEFINED #define _REFCLSID_DEFINED #ifdef __cplusplus -#define REFCLSID const IID & +#define REFCLSID const IID& #else -#define REFCLSID const IID * __MIDL_CONST +#define REFCLSID const IID* __MIDL_CONST #endif #endif #ifndef _REFFMTID_DEFINED #define _REFFMTID_DEFINED #ifdef __cplusplus -#define REFFMTID const IID & +#define REFFMTID const IID& #else -#define REFFMTID const IID * __MIDL_CONST +#define REFFMTID const IID* __MIDL_CONST #endif #endif #endif // !__IID_DEFINED__ -#if !defined (__midl) -#if !defined (_SYS_GUID_OPERATORS_) +#if !defined(__midl) +#if !defined(_SYS_GUID_OPERATORS_) #define _SYS_GUID_OPERATORS_ #include @@ -164,29 +164,29 @@ typedef FMTID *LPFMTID; #ifdef __cplusplus __inline int InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2) { - return ( - ((unsigned long *) &rguid1)[0] == ((unsigned long *) &rguid2)[0] && - ((unsigned long *) &rguid1)[1] == ((unsigned long *) &rguid2)[1] && - ((unsigned long *) &rguid1)[2] == ((unsigned long *) &rguid2)[2] && - ((unsigned long *) &rguid1)[3] == ((unsigned long *) &rguid2)[3]); + return ( + ((unsigned long*)&rguid1)[0] == ((unsigned long*)&rguid2)[0] + && ((unsigned long*)&rguid1)[1] == ((unsigned long*)&rguid2)[1] + && ((unsigned long*)&rguid1)[2] == ((unsigned long*)&rguid2)[2] + && ((unsigned long*)&rguid1)[3] == ((unsigned long*)&rguid2)[3]); } __inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) { - return !memcmp(&rguid1, &rguid2, sizeof(GUID)); + return !memcmp(&rguid1, &rguid2, sizeof(GUID)); } -#else // ! __cplusplus +#else // ! __cplusplus -#define InlineIsEqualGUID(rguid1, rguid2) \ - (((unsigned long *) rguid1)[0] == ((unsigned long *) rguid2)[0] && \ - ((unsigned long *) rguid1)[1] == ((unsigned long *) rguid2)[1] && \ - ((unsigned long *) rguid1)[2] == ((unsigned long *) rguid2)[2] && \ - ((unsigned long *) rguid1)[3] == ((unsigned long *) rguid2)[3]) +#define InlineIsEqualGUID(rguid1, rguid2) \ + (((unsigned long*)rguid1)[0] == ((unsigned long*)rguid2)[0] \ + && ((unsigned long*)rguid1)[1] == ((unsigned long*)rguid2)[1] \ + && ((unsigned long*)rguid1)[2] == ((unsigned long*)rguid2)[2] \ + && ((unsigned long*)rguid1)[3] == ((unsigned long*)rguid2)[3]) #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID))) -#endif // __cplusplus +#endif // __cplusplus #ifdef __INLINE_ISEQUAL_GUID #undef IsEqualGUID @@ -198,7 +198,6 @@ __inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) #define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) #define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) - #if !defined _SYS_GUID_OPERATOR_EQ_ && !defined _NO_SYS_GUID_OPERATOR_EQ_ #define _SYS_GUID_OPERATOR_EQ_ // A couple of C++ helpers @@ -206,16 +205,16 @@ __inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) #ifdef __cplusplus __inline bool operator==(REFGUID guidOne, REFGUID guidOther) { - return !!IsEqualGUID(guidOne,guidOther); + return !!IsEqualGUID(guidOne, guidOther); } __inline bool operator!=(REFGUID guidOne, REFGUID guidOther) { - return !(guidOne == guidOther); + return !(guidOne == guidOther); } #endif -#endif // _SYS_GUID_OPERATOR_EQ_ -#endif // _SYS_GUID_OPERATORS_ -#endif // __midl -#endif // _GUIDDEF_H_ +#endif // _SYS_GUID_OPERATOR_EQ_ +#endif // _SYS_GUID_OPERATORS_ +#endif // __midl +#endif // _GUIDDEF_H_ diff --git a/libs/smartPtr/include/core/TCntPtr.h b/libs/smartPtr/include/core/TCntPtr.h index 29c7879..5ebdae9 100644 --- a/libs/smartPtr/include/core/TCntPtr.h +++ b/libs/smartPtr/include/core/TCntPtr.h @@ -18,97 +18,93 @@ namespace Mso { class ObjectWeakRef; /** - Simple ref-counting + Simple ref-counting */ struct DECLSPEC_NOVTABLE IRefCounted { - virtual void AddRef() const noexcept = 0; - virtual void Release() const noexcept = 0; + virtual void AddRef() const noexcept = 0; + virtual void Release() const noexcept = 0; }; /** - Provides weak ref-counting support at interface level: when there is a need to convert - TCntPtr to WeakPtr, deriving IFoo from IWeakRefCounted ensures that there - is no run-time error tag_bad22 (under condition that implementations of IFoo are derived - from RefCountedObject). + Provides weak ref-counting support at interface level: when there is a need to convert + TCntPtr to WeakPtr, deriving IFoo from IWeakRefCounted ensures that there + is no run-time error tag_bad22 (under condition that implementations of IFoo are derived + from RefCountedObject). */ struct DECLSPEC_NOVTABLE IWeakRefCounted : public IRefCounted { - virtual ObjectWeakRef& GetWeakRef() const noexcept = 0; + virtual ObjectWeakRef& GetWeakRef() const noexcept = 0; }; /** - DEPRECATED: please use Mso::RefCountedObject + DEPRECATED: please use Mso::RefCountedObject - Provides implementation for an interface with AddRef + Release - MostDerivedInterface is the IRefCounted-derived interface you are implementing. + Provides implementation for an interface with AddRef + Release + MostDerivedInterface is the IRefCounted-derived interface you are implementing. - e.g. - interface IMyInterface : public Mso::IRefCounted { ... }; + e.g. + interface IMyInterface : public Mso::IRefCounted { ... }; - class MyInterfaceImpl : public Mso::TRefCountedImpl< IMyInterface > - { - // Override method from IMyInterface - // No need for implementing IRefCounted methods - }; + class MyInterfaceImpl : public Mso::TRefCountedImpl< IMyInterface > + { + // Override method from IMyInterface + // No need for implementing IRefCounted methods + }; */ -template< class ...TInterfaces > +template class TRefCountedImpl : public TInterfaces... { - OACR_MARK_CLASS_DEPRECATED(Mso::RefCountedObject) + OACR_MARK_CLASS_DEPRECATED(Mso::RefCountedObject) public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TRefCountedImpl); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TRefCountedImpl); - virtual void AddRef() const noexcept override - { - m_ref++; - } + virtual void AddRef() const noexcept override + { + m_ref++; + } - virtual void Release() const noexcept override - { - if (m_ref.fetch_sub(1) == 1) - delete this; - } + virtual void Release() const noexcept override + { + if (m_ref.fetch_sub(1) == 1) + delete this; + } protected: - TRefCountedImpl() noexcept : m_ref(0) - { - } + TRefCountedImpl() noexcept : m_ref(0) {} - virtual ~TRefCountedImpl() noexcept - { - } + virtual ~TRefCountedImpl() noexcept {} - uint32_t GetRefCount() const noexcept - { - return m_ref.load(); - } + uint32_t GetRefCount() const noexcept + { + return m_ref.load(); + } private: - mutable std::atomic m_ref; - #pragma warning( suppress : 4820 ) // 4 bytes padding added after data member + mutable std::atomic m_ref; +#pragma warning(suppress : 4820) // 4 bytes padding added after data member }; /** - Manages a pointer cleaned up with Release() + Manages a pointer cleaned up with Release() */ template struct TReleaseHelper { - static void Free(T pT) noexcept - { - using ArrowType = decltype(Mso::RawTraits::GetArrowType(pT)); - using NonConstArrowType = std::remove_const_t>; - const_cast(Mso::RawTraits::GetArrowType(pT))->Release(); - } + static void Free(T pT) noexcept + { + using ArrowType = decltype(Mso::RawTraits::GetArrowType(pT)); + using NonConstArrowType = std::remove_const_t>; + const_cast(Mso::RawTraits::GetArrowType(pT))->Release(); + } }; -template class TCntPtr; +template +class TCntPtr; // Code in details namespace is for internal usage only -namespace Details -{ +namespace Details { /// Used for TCntPtr operator& implementation. /// It allows to avoid memory leaks when non-empty TCntPtr is used as output parameter T**. @@ -116,582 +112,664 @@ namespace Details template class TCntPtrRef { - // We only allow TCntPtr to make instance of this type - template friend class Mso::TCntPtr; + // We only allow TCntPtr to make instance of this type + template + friend class Mso::TCntPtr; public: - operator Mso::TCntPtr*() noexcept{ return m_pTCntPtr; } - operator void*() noexcept { return m_pTCntPtr; } - operator T**() noexcept { return m_pTCntPtr->GetAddressOf(); } - operator void**() noexcept { return reinterpret_cast(m_pTCntPtr->GetAddressOf()); } - operator const void**() noexcept { return reinterpret_cast(const_cast(m_pTCntPtr->GetAddressOf())); } + operator Mso::TCntPtr *() noexcept + { + return m_pTCntPtr; + } + operator void*() noexcept + { + return m_pTCntPtr; + } + operator T* *() noexcept + { + return m_pTCntPtr->GetAddressOf(); + } + operator void* *() noexcept + { + return reinterpret_cast(m_pTCntPtr->GetAddressOf()); + } + operator const void* *() noexcept + { + return reinterpret_cast(const_cast(m_pTCntPtr->GetAddressOf())); + } - // If you are sure it is safe, use static_cast(&p) to access this operator - template ::value>> - explicit operator U**() const noexcept - { - return reinterpret_cast(m_pTCntPtr->GetAddressOf()); - } + // If you are sure it is safe, use static_cast(&p) to access this operator + template ::value>> + explicit operator U* *() const noexcept + { + return reinterpret_cast(m_pTCntPtr->GetAddressOf()); + } - T*& operator*() noexcept { return *(m_pTCntPtr->GetAddressOf()); } - T** GetRaw() const noexcept { return m_pTCntPtr->GetRaw(); } - T* const* GetAddressOf() const noexcept { return m_pTCntPtr->GetAddressOf(); } - T** ClearAndGetAddressOf() noexcept { return m_pTCntPtr->ClearAndGetAddressOf(); } + T*& operator*() noexcept + { + return *(m_pTCntPtr->GetAddressOf()); + } + T** GetRaw() const noexcept + { + return m_pTCntPtr->GetRaw(); + } + T* const* GetAddressOf() const noexcept + { + return m_pTCntPtr->GetAddressOf(); + } + T** ClearAndGetAddressOf() noexcept + { + return m_pTCntPtr->ClearAndGetAddressOf(); + } private: - TCntPtrRef(_In_ Mso::TCntPtr* pT) noexcept : m_pTCntPtr(pT) {} + TCntPtrRef(_In_ Mso::TCntPtr* pT) noexcept : m_pTCntPtr(pT) {} private: - Mso::TCntPtr* m_pTCntPtr; + Mso::TCntPtr* m_pTCntPtr; }; template bool operator==(const TCntPtrRef& left, const TCntPtrRef& right) noexcept { - static_assert(std::is_base_of::value || std::is_base_of::value, "'T' and 'U' pointers must be comparable"); - return left.GetRaw() == right.GetRaw(); + static_assert( + std::is_base_of::value || std::is_base_of::value, "'T' and 'U' pointers must be comparable"); + return left.GetRaw() == right.GetRaw(); } template bool operator!=(const TCntPtrRef& left, const TCntPtrRef& right) noexcept { - return !(left == right); + return !(left == right); } } // namespace Details /** - The TCntPtrAddRefStrategy enumeration and TCntPtrAddRefStrategyForType template allows the - code to specify how specific types of TCntPtr's will perform the add ref operation + The TCntPtrAddRefStrategy enumeration and TCntPtrAddRefStrategyForType template allows the + code to specify how specific types of TCntPtr's will perform the add ref operation */ enum TCntPtrAddRefStrategy : uint32_t { - AddRef = 0, - RefTrack = 1, + AddRef = 0, + RefTrack = 1, }; /** - To change the type of RefCount strategy that a particular type of TCntPtr will use - override this general template with one specific to the pointer type + To change the type of RefCount strategy that a particular type of TCntPtr will use + override this general template with one specific to the pointer type */ template struct TCntPtrAddRefStrategyForType { - static const TCntPtrAddRefStrategy Strategy = TCntPtrAddRefStrategy::AddRef; + static const TCntPtrAddRefStrategy Strategy = TCntPtrAddRefStrategy::AddRef; }; // Code in details namespace is for internal usage only -namespace Details -{ +namespace Details { /** - Implements CheckedAddRef for ref counted interfaces that are not using RefTrack + Implements CheckedAddRef for ref counted interfaces that are not using RefTrack - Q: What is this strategy only applied to TCntPtr and not TCntRef - A: TCntRef has a Copy method that does AddRef and then returns a reference to the - object. This is not compatible with RefTrack and so the strategy is not applied. + Q: What is this strategy only applied to TCntPtr and not TCntRef + A: TCntRef has a Copy method that does AddRef and then returns a reference to the + object. This is not compatible with RefTrack and so the strategy is not applied. */ -template +template struct TCntPtrAddRefStrategyImpl { - /** - Safely performs an AddRef on the newly assigned ptr value, this means that the caller does - not currently have a reference on the supplied value. - */ - template - static void CheckedAddRefOnNewlyAssignedPtr(_Inout_ _Deref_pre_valid_ _Deref_post_valid_ T** ppT) noexcept - { - using TNonConst = typename std::remove_const::type; // For AddRef() and Release() calls + /** + Safely performs an AddRef on the newly assigned ptr value, this means that the caller does + not currently have a reference on the supplied value. + */ + template + static void CheckedAddRefOnNewlyAssignedPtr(_Inout_ _Deref_pre_valid_ _Deref_post_valid_ T** ppT) noexcept + { + using TNonConst = typename std::remove_const::type; // For AddRef() and Release() calls - if (*ppT) - { - const_cast(*ppT)->AddRef(); - } - } + if (*ppT) + { + const_cast(*ppT)->AddRef(); + } + } - /** - Depending upon the RefCount strategy used it may be necessary to unwrap the IUnknown before - it is used for comparing to determine object identity. By default we just use the provided - IUnknown value. - */ - template - static T* GetIUnknownForObjectCompare(T* pValue) - { - return pValue; - } + /** + Depending upon the RefCount strategy used it may be necessary to unwrap the IUnknown before + it is used for comparing to determine object identity. By default we just use the provided + IUnknown value. + */ + template + static T* GetIUnknownForObjectCompare(T* pValue) + { + return pValue; + } }; /** - Allows for the AddRefStrategy for the type to be obtained. This is needed when using the - strategy outside of a tempalte class. + Allows for the AddRefStrategy for the type to be obtained. This is needed when using the + strategy outside of a tempalte class. */ template struct AddRefStrategyForType { - using TAddRefStrategy = TCntPtrAddRefStrategyForType; + using TAddRefStrategy = TCntPtrAddRefStrategyForType; }; } // namespace Details /** - Ref-counted smart pointer, once set always the same, never null. - Typically used for member variables. - Methods will assert if TCntRef is used after its content is moved to another TCntRef. + Ref-counted smart pointer, once set always the same, never null. + Typically used for member variables. + Methods will assert if TCntRef is used after its content is moved to another TCntRef. */ template class TCntRef final { public: - TCntRef() noexcept : m_pT(nullptr) {} + TCntRef() noexcept : m_pT(nullptr) {} - explicit TCntRef(T& ref, bool fDoAddRef = true) noexcept : m_pT(&ref) - { - if (fDoAddRef) CheckedAddRef(m_pT); - } + explicit TCntRef(T& ref, bool fDoAddRef = true) noexcept : m_pT(&ref) + { + if (fDoAddRef) + CheckedAddRef(m_pT); + } - template ::value>::type> - explicit TCntRef(TOther& ref, bool fDoAddRef = true) noexcept : m_pT(&ref) - { - if (fDoAddRef) CheckedAddRef(m_pT); - } + template ::value>::type> + explicit TCntRef(TOther& ref, bool fDoAddRef = true) noexcept : m_pT(&ref) + { + if (fDoAddRef) + CheckedAddRef(m_pT); + } - TCntRef(const TCntRef& other) noexcept : m_pT(other.Ptr()) - { - CheckedAddRef(m_pT); - } + TCntRef(const TCntRef& other) noexcept : m_pT(other.Ptr()) + { + CheckedAddRef(m_pT); + } - template ::value>::type> - TCntRef(const Mso::TCntRef& other) noexcept : m_pT(other.Ptr()) - { - CheckedAddRef(m_pT); - } + template ::value>::type> + TCntRef(const Mso::TCntRef& other) noexcept : m_pT(other.Ptr()) + { + CheckedAddRef(m_pT); + } - TCntRef(TCntRef&& other) noexcept : m_pT(other.Ptr()) - { - other.m_pT = nullptr; - } + TCntRef(TCntRef&& other) noexcept : m_pT(other.Ptr()) + { + other.m_pT = nullptr; + } - template ::value>::type> - TCntRef(Mso::TCntRef&& other) noexcept : m_pT(other.Ptr()) - { - other.m_pT = nullptr; - } + template ::value>::type> + TCntRef(Mso::TCntRef&& other) noexcept : m_pT(other.Ptr()) + { + other.m_pT = nullptr; + } - TCntRef& operator=(const TCntRef& other) = delete; - TCntRef& operator=(TCntRef&& other) = delete; + TCntRef& operator=(const TCntRef& other) = delete; + TCntRef& operator=(TCntRef&& other) = delete; - ~TCntRef() noexcept - { - Clear(); - } + ~TCntRef() noexcept + { + Clear(); + } - bool IsEmpty() const noexcept - { - return m_pT == nullptr; - } + bool IsEmpty() const noexcept + { + return m_pT == nullptr; + } - T* Ptr() const noexcept - { - AssertTag(m_pT, 0x0152139d /* tag_bu7o3 */); - return const_cast(this)->m_pT; - } + T* Ptr() const noexcept + { + AssertTag(m_pT, 0x0152139d /* tag_bu7o3 */); + return const_cast(this)->m_pT; + } - T& Get() const noexcept - { - VerifyElseCrashTag(m_pT, 0x0152139e /* tag_bu7o4 */); - return *const_cast(this)->m_pT; - } + T& Get() const noexcept + { + VerifyElseCrashTag(m_pT, 0x0152139e /* tag_bu7o4 */); + return *const_cast(this)->m_pT; + } #ifndef MSO_THOLDER_EXPLICIT_GET_ONLY - /// Implicit cast operator - /*_SA_deprecated_(Get)*/ operator T&() const noexcept - { - return Get(); - } + /// Implicit cast operator + /*_SA_deprecated_(Get)*/ operator T&() const noexcept + { + return Get(); + } #endif - /// Returns an AddRef'd raw reference - T& Copy() const noexcept - { - T& ref = Get(); - CheckedAddRef(&ref); - return ref; - } + /// Returns an AddRef'd raw reference + T& Copy() const noexcept + { + T& ref = Get(); + CheckedAddRef(&ref); + return ref; + } - /// Copy to a naked pointer and AddRef - template - void AssignTo(_Out_opt_ TOther *ppT) const noexcept - { - AssertTag(ppT != nullptr, 0x0152139f /* tag_bu7o5 */); - if (ppT != nullptr) - *ppT = Copy(); - } + /// Copy to a naked pointer and AddRef + template + void AssignTo(_Out_opt_ TOther* ppT) const noexcept + { + AssertTag(ppT != nullptr, 0x0152139f /* tag_bu7o5 */); + if (ppT != nullptr) + *ppT = Copy(); + } #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY - explicit operator bool() const noexcept - { - return !IsEmpty(); - } + explicit operator bool() const noexcept + { + return !IsEmpty(); + } #endif - T* operator->() const noexcept - { - VerifyElseCrashTag(m_pT, 0x015213a0 /* tag_bu7o6 */); - return const_cast(this)->m_pT; - } + T* operator->() const noexcept + { + VerifyElseCrashTag(m_pT, 0x015213a0 /* tag_bu7o6 */); + return const_cast(this)->m_pT; + } private: - using TNonConst = typename std::remove_const::type; + using TNonConst = typename std::remove_const::type; - static void CheckedAddRef(T* pT) noexcept - { - if (pT) - { - const_cast(pT)->AddRef(); - } - } + static void CheckedAddRef(T* pT) noexcept + { + if (pT) + { + const_cast(pT)->AddRef(); + } + } - void Clear() noexcept - { - if (m_pT) - { - TNonConst* pT = const_cast(m_pT); - m_pT = nullptr; - (void) pT; // To avoid compilation warnings - pT->Release(); - } - } + void Clear() noexcept + { + if (m_pT) + { + TNonConst* pT = const_cast(m_pT); + m_pT = nullptr; + (void)pT; // To avoid compilation warnings + pT->Release(); + } + } private: - T* m_pT; + T* m_pT; - template friend class TCntRef; + template + friend class TCntRef; }; #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY /** - Operators for TCntRef + Operators for TCntRef */ template bool operator==(const TCntRef& left, const TCntRef& right) noexcept { - return (&left.Get() == &right.Get()); + return (&left.Get() == &right.Get()); } template bool operator!=(const TCntRef& left, const TCntRef& right) noexcept { - return !(left == right); + return !(left == right); } #endif // MSO_THOLDER_EXPLICIT_GET_ONLY /** - Ref-counted smart pointer, possibly null + Ref-counted smart pointer, possibly null */ template class TCntPtr { - using TNonConst = typename std::remove_const::type; // For AddRef() and Release() calls - using TAddrType = T**; - using TAddRefStrategy = TCntPtrAddRefStrategyForType; + using TNonConst = typename std::remove_const::type; // For AddRef() and Release() calls + using TAddrType = T**; + using TAddRefStrategy = TCntPtrAddRefStrategyForType; public: - /** - Constructors - */ + /** + Constructors + */ - TCntPtr() noexcept : m_pT(nullptr) {} - explicit TCntPtr(std::nullptr_t) noexcept : m_pT(nullptr) {} + TCntPtr() noexcept : m_pT(nullptr) {} + explicit TCntPtr(std::nullptr_t) noexcept : m_pT(nullptr) {} - // Expressly delete the legacy NULL ctor - TCntPtr(int) = delete; + // Expressly delete the legacy NULL ctor + TCntPtr(int) = delete; - // TODO: This should be explicit, but it requires fixing a lot of code - /*explicit*/ TCntPtr(_In_opt_ T* pT, bool fDoAddRef = true) noexcept : m_pT(pT) - { - if (fDoAddRef) Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); - } + // TODO: This should be explicit, but it requires fixing a lot of code + /*explicit*/ TCntPtr(_In_opt_ T* pT, bool fDoAddRef = true) noexcept : m_pT(pT) + { + if (fDoAddRef) + Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); + } - template ::value>::type> - explicit TCntPtr(_In_opt_ TOther* pOther, bool fDoAddRef = true) noexcept : m_pT(pOther) - { - if (fDoAddRef) Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); - } + template ::value>::type> + explicit TCntPtr(_In_opt_ TOther* pOther, bool fDoAddRef = true) noexcept : m_pT(pOther) + { + if (fDoAddRef) + Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); + } - // Delete this constructor. Developers must be explicit in their code when they want to use unsafe conversion from void* or from a base class. - // Use TCntPtr(static_cast(ptr)) or qi_cast(ptr) instead. - template ::value>::type> - explicit TCntPtr(_In_opt_ TOther* pOther, bool fDoAddRef = true, int /*doNotUseThisConstructor*/ = 0) = delete; + // Delete this constructor. Developers must be explicit in their code when they want to use unsafe conversion from + // void* or from a base class. Use TCntPtr(static_cast(ptr)) or qi_cast(ptr) instead. + template ::value>::type> + explicit TCntPtr(_In_opt_ TOther* pOther, bool fDoAddRef = true, int /*doNotUseThisConstructor*/ = 0) = delete; - TCntPtr(const TCntPtr& from) noexcept : m_pT(from.Get()) - { - Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); - } + TCntPtr(const TCntPtr& from) noexcept : m_pT(from.Get()) + { + Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); + } - template ::value>::type> - TCntPtr(const Mso::TCntPtr& from) noexcept : m_pT(from.Get()) - { - Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); - } + template ::value>::type> + TCntPtr(const Mso::TCntPtr& from) noexcept : m_pT(from.Get()) + { + Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&m_pT); + } - TCntPtr(TCntPtr&& from) noexcept : m_pT(from.Detach()) {} - - template ::value>::type> - TCntPtr(Mso::TCntPtr&& from) noexcept : m_pT(from.Detach()) {} + TCntPtr(TCntPtr&& from) noexcept : m_pT(from.Detach()) {} - template - TCntPtr(const Mso::TCntRef& from) noexcept - : TCntPtr{from.Ptr()} - { - } + template ::value>::type> + TCntPtr(Mso::TCntPtr&& from) noexcept : m_pT(from.Detach()) + { + } - ~TCntPtr() noexcept - { - Clear(); - } + template + TCntPtr(const Mso::TCntRef& from) noexcept : TCntPtr{from.Ptr()} + { + } - /** - operator = - */ + ~TCntPtr() noexcept + { + Clear(); + } - TCntPtr& operator=(std::nullptr_t) noexcept - { - this->Clear(); - return *this; - } + /** + operator = + */ - template< typename TOther, typename = typename std::enable_if< std::is_base_of< T, TOther >::value >::type > - TCntPtr& operator=(_In_opt_ TOther* pT) noexcept - { - if (m_pT != pT) - { - T* pNew = pT; - Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&pNew); + TCntPtr& operator=(std::nullptr_t) noexcept + { + this->Clear(); + return *this; + } - Clear(); - m_pT = pNew; - } - return *this; - } + template ::value>::type> + TCntPtr& operator=(_In_opt_ TOther* pT) noexcept + { + if (m_pT != pT) + { + T* pNew = pT; + Details::TCntPtrAddRefStrategyImpl::CheckedAddRefOnNewlyAssignedPtr(&pNew); - TCntPtr& operator=(const TCntPtr& from) noexcept - { - return operator=(from.Get()); - } + Clear(); + m_pT = pNew; + } + return *this; + } - template ::value>::type> - TCntPtr& operator=(const Mso::TCntPtr& from) noexcept - { - return operator=(from.Get()); - } + TCntPtr& operator=(const TCntPtr& from) noexcept + { + return operator=(from.Get()); + } - TCntPtr& operator=(TCntPtr&& from) noexcept - { - Mso::TCntPtr(std::move(from)).Swap(*this); - return *this; - } + template ::value>::type> + TCntPtr& operator=(const Mso::TCntPtr& from) noexcept + { + return operator=(from.Get()); + } - template ::value>::type> - TCntPtr& operator=(Mso::TCntPtr&& from) noexcept - { - Mso::TCntPtr(std::move(from)).Swap(*this); - return *this; - } + TCntPtr& operator=(TCntPtr&& from) noexcept + { + Mso::TCntPtr(std::move(from)).Swap(*this); + return *this; + } - /// The rare case that you need a pointer to the smart pointer itself - const TCntPtr* GetThis() const noexcept { return this; } - TCntPtr* GetThis() noexcept { return this; } + template ::value>::type> + TCntPtr& operator=(Mso::TCntPtr&& from) noexcept + { + Mso::TCntPtr(std::move(from)).Swap(*this); + return *this; + } - /// Return an AddRef'd raw pointer - T* Copy() const noexcept - { - TCntPtr copy(m_pT); - return copy.Detach(); - } + /// The rare case that you need a pointer to the smart pointer itself + const TCntPtr* GetThis() const noexcept + { + return this; + } + TCntPtr* GetThis() noexcept + { + return this; + } - /// Explicitly delete owned object - void Clear() noexcept - { - if (m_pT) - { - TNonConst* pT = const_cast(m_pT); - m_pT = nullptr; - (void) pT; // to avoid compilation warnings - pT->Release(); - } - } + /// Return an AddRef'd raw pointer + T* Copy() const noexcept + { + TCntPtr copy(m_pT); + return copy.Detach(); + } - bool IsEmpty() const noexcept - { - return (m_pT == nullptr); - } + /// Explicitly delete owned object + void Clear() noexcept + { + if (m_pT) + { + TNonConst* pT = const_cast(m_pT); + m_pT = nullptr; + (void)pT; // to avoid compilation warnings + pT->Release(); + } + } + + bool IsEmpty() const noexcept + { + return (m_pT == nullptr); + } #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY - explicit operator bool() const noexcept - { - return !IsEmpty(); - } + explicit operator bool() const noexcept + { + return !IsEmpty(); + } - T& operator*() const noexcept - { - return *Get(); - } + T& operator*() const noexcept + { + return *Get(); + } #endif - T* Get() const noexcept - { - return const_cast(this)->m_pT; - } + T* Get() const noexcept + { + return const_cast(this)->m_pT; + } #ifndef MSO_THOLDER_EXPLICIT_GET_ONLY - /// Implicit cast operator - /*_SA_deprecated_(Get)*/ operator T*() const noexcept - { - return m_pT; - } + /// Implicit cast operator + /*_SA_deprecated_(Get)*/ operator T*() const noexcept + { + return m_pT; + } #endif - T* operator->() const noexcept - { - VerifyElseCrashTag(m_pT, 0x0152139a /* tag_bu7o0 */); - return const_cast(this)->m_pT; - } + T* operator->() const noexcept + { + VerifyElseCrashTag(m_pT, 0x0152139a /* tag_bu7o0 */); + return const_cast(this)->m_pT; + } - void Swap(TCntPtr& other) noexcept - { - T* pT = m_pT; - m_pT = other.m_pT; - other.m_pT = pT; - } + void Swap(TCntPtr& other) noexcept + { + T* pT = m_pT; + m_pT = other.m_pT; + other.m_pT = pT; + } - /// Take object ownership, m_pT must be empty - T* Place(T* pT) noexcept - { - AssertTag(IsEmpty(), 0x0152139b /* tag_bu7o1 */); - m_pT = pT; - return m_pT; - } + /// Take object ownership, m_pT must be empty + T* Place(T* pT) noexcept + { + AssertTag(IsEmpty(), 0x0152139b /* tag_bu7o1 */); + m_pT = pT; + return m_pT; + } - /// Take object ownership, deletes previously owned object if any - T* Attach(T* pT) noexcept - { - Clear(); - m_pT = pT; - return m_pT; - } + /// Take object ownership, deletes previously owned object if any + T* Attach(T* pT) noexcept + { + Clear(); + m_pT = pT; + return m_pT; + } - /// Release ownership without deleting object - T* Detach() noexcept - { - T* pT = m_pT; - m_pT = nullptr; - return pT; - } + /// Release ownership without deleting object + T* Detach() noexcept + { + T* pT = m_pT; + m_pT = nullptr; + return pT; + } - /// & operator to retrieve object. - /// Returned TCntPtrRef takes care about safe use of the pointer. - Mso::Details::TCntPtrRef operator&() noexcept - { - return Mso::Details::TCntPtrRef(this); - } + /// & operator to retrieve object. + /// Returned TCntPtrRef takes care about safe use of the pointer. + Mso::Details::TCntPtrRef operator&() noexcept + { + return Mso::Details::TCntPtrRef(this); + } - /** - Retrieves the address of the object. Asserts that TCntPtr is empty. + /** + Retrieves the address of the object. Asserts that TCntPtr is empty. - void GetSomething(T** ppT); + void GetSomething(T** ppT); - Mso::TCntPtr pT; - GetSomething(pT.GetAddressOf()); + Mso::TCntPtr pT; + GetSomething(pT.GetAddressOf()); - ClearAndGetAddressOf() will ensure any existing object is cleared first. - GetRaw() avoids the assert if you need the address of an existing object. - */ - TAddrType GetAddressOf() noexcept - { - AssertSzTag(IsEmpty(), "Getting the address of an existing object? This usually leads to a leak.", 0x0152139c /* tag_bu7o2 */); - return GetRaw(); - } + ClearAndGetAddressOf() will ensure any existing object is cleared first. + GetRaw() avoids the assert if you need the address of an existing object. + */ + TAddrType GetAddressOf() noexcept + { + AssertSzTag( + IsEmpty(), + "Getting the address of an existing object? This usually leads to a leak.", + 0x0152139c /* tag_bu7o2 */); + return GetRaw(); + } - /**/ - TAddrType ClearAndGetAddressOf() noexcept - { - Clear(); - return GetRaw(); - } + /**/ + TAddrType ClearAndGetAddressOf() noexcept + { + Clear(); + return GetRaw(); + } - /**/ - TAddrType GetRaw() noexcept - { - // This is dangerous so you better know what you are doing - return &m_pT; - } + /**/ + TAddrType GetRaw() noexcept + { + // This is dangerous so you better know what you are doing + return &m_pT; + } - /** - Deprecated API to remove over time. - */ - /*_SA_deprecated_(Get)*/ T* get() const noexcept { return this->Get(); } - /*_SA_deprecated_(Swap)*/ void swap(TCntPtr& from) noexcept { Swap(from); } - /*_SA_deprecated_(Clear)*/ void clear() noexcept { this->Clear(); } - /*_SA_deprecated_(Clear)*/ void Empty() noexcept { Clear(); } - /*_SA_deprecated_(Clear)*/ void Free() noexcept { Clear(); } - /*_SA_deprecated_(Clear)*/ void Close() noexcept { Clear(); } - /*_SA_deprecated_(Clear)*/ void Release() noexcept { Clear(); } - /*_SA_deprecated_(IsEmpty)*/ bool FIsEmpty() const noexcept { return IsEmpty(); } - /*_SA_deprecated_(Detach)*/ T* Extract() noexcept { return Detach(); } - template - /*_SA_deprecated_(move assignment)*/ void TransferFrom(_Inout_ TCntPtr& from) noexcept { Attach(from.Detach()); } - template - /*_SA_deprecated_(move assignment)*/ void Transfer(TCntPtr& from) noexcept { return TransferFrom(from); } - /*_SA_deprecated_(GetAddressOf)*/ TAddrType Ptr() noexcept { return this->GetAddressOf(); } - /*_SA_deprecated_(ClearAndGetAddressOf)*/ TAddrType Address() noexcept { return this->ClearAndGetAddressOf(); } + /** + Deprecated API to remove over time. + */ + /*_SA_deprecated_(Get)*/ T* get() const noexcept + { + return this->Get(); + } + /*_SA_deprecated_(Swap)*/ void swap(TCntPtr& from) noexcept + { + Swap(from); + } + /*_SA_deprecated_(Clear)*/ void clear() noexcept + { + this->Clear(); + } + /*_SA_deprecated_(Clear)*/ void Empty() noexcept + { + Clear(); + } + /*_SA_deprecated_(Clear)*/ void Free() noexcept + { + Clear(); + } + /*_SA_deprecated_(Clear)*/ void Close() noexcept + { + Clear(); + } + /*_SA_deprecated_(Clear)*/ void Release() noexcept + { + Clear(); + } + /*_SA_deprecated_(IsEmpty)*/ bool FIsEmpty() const noexcept + { + return IsEmpty(); + } + /*_SA_deprecated_(Detach)*/ T* Extract() noexcept + { + return Detach(); + } + template + /*_SA_deprecated_(move assignment)*/ void TransferFrom(_Inout_ TCntPtr& from) noexcept + { + Attach(from.Detach()); + } + template + /*_SA_deprecated_(move assignment)*/ void Transfer(TCntPtr& from) noexcept + { + return TransferFrom(from); + } + /*_SA_deprecated_(GetAddressOf)*/ TAddrType Ptr() noexcept + { + return this->GetAddressOf(); + } + /*_SA_deprecated_(ClearAndGetAddressOf)*/ TAddrType Address() noexcept + { + return this->ClearAndGetAddressOf(); + } private: - T* m_pT; + T* m_pT; }; #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY /** - Operators for TCntPtr + Operators for TCntPtr */ template bool operator==(const TCntPtr& left, const TCntPtr& right) noexcept { - return (left.Get() == right.Get()); + return (left.Get() == right.Get()); } template bool operator==(const TCntPtr& left, std::nullptr_t) noexcept { - return left.IsEmpty(); + return left.IsEmpty(); } template bool operator==(std::nullptr_t, const TCntPtr& right) noexcept { - return right.IsEmpty(); + return right.IsEmpty(); } template bool operator!=(const TCntPtr& left, const TCntPtr& right) noexcept { - return !(left == right); + return !(left == right); } template bool operator!=(const TCntPtr& left, std::nullptr_t) noexcept { - return !left.IsEmpty(); + return !left.IsEmpty(); } template bool operator!=(std::nullptr_t, const TCntPtr& right) noexcept { - return !right.IsEmpty(); + return !right.IsEmpty(); } #endif // MSO_THOLDER_EXPLICIT_GET_ONLY -} // Mso +} // namespace Mso #endif // __cplusplus #endif // LIBLET_CORE_TCNTPTR_H \ No newline at end of file diff --git a/libs/smartPtr/include/core/smartHandles.h b/libs/smartPtr/include/core/smartHandles.h index ac6eaaf..0467761 100644 --- a/libs/smartPtr/include/core/smartHandles.h +++ b/libs/smartPtr/include/core/smartHandles.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Helper classes for managing handles + Helper classes for managing handles */ #pragma once #ifndef LIBLET_CORE_SMARTHANDLES_H @@ -16,22 +16,22 @@ namespace Mso { /** - Manages a HANDLE + Manages a HANDLE */ struct HandleHelper - { - static void Free(HANDLE h) noexcept - { - ::CloseHandle(h); - } - }; +{ + static void Free(HANDLE h) noexcept + { + ::CloseHandle(h); + } +}; /** - HANDLE holder + HANDLE holder */ typedef THolder HandleHolder; -} // Mso +} // namespace Mso #endif // __cplusplus diff --git a/libs/smartPtr/include/core/smartPointers.h b/libs/smartPtr/include/core/smartPointers.h index 9f55117..1f53a52 100644 --- a/libs/smartPtr/include/core/smartPointers.h +++ b/libs/smartPtr/include/core/smartPointers.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Definitions for generic smart pointers + Definitions for generic smart pointers */ #pragma once #ifndef LIBLET_CORE_SMARTPOINTERS_H @@ -13,166 +13,202 @@ namespace Mso { /** - Manages a pointer allocated with new + Manages a pointer allocated with new */ -template< typename T > struct TDeleteHelper +template +struct TDeleteHelper { - static void Free(T pT) noexcept - { - delete pT; - } + static void Free(T pT) noexcept + { + delete pT; + } }; /** - Smart pointer for a pointer deleted with delete - typename T should not include the pointer - TOwnerPtr pFoo( new CFoo() ); + Smart pointer for a pointer deleted with delete + typename T should not include the pointer + TOwnerPtr pFoo( new CFoo() ); - Prefer to use std::unique_ptr. + Prefer to use std::unique_ptr. */ -template class TOwnerPtr : public THolder> +template +class TOwnerPtr : public THolder> { - typedef THolder> Super; -public: - TOwnerPtr() noexcept {} - /*explicit*/ TOwnerPtr(T *pT) noexcept : Super(pT) {} - IMPLEMENT_THOLDER_OPERATOR_EQUALS(TOwnerPtr); - IMPLEMENT_THOLDER_RVALUE_REFS(TOwnerPtr); + typedef THolder> Super; - T* get() noexcept { return Super::Get(); } - const T* get() const noexcept { return Super::Get(); } - T* release() noexcept { return Super::Detach(); } - void reset(T* pT) noexcept { this = pT; } +public: + TOwnerPtr() noexcept {} + /*explicit*/ TOwnerPtr(T* pT) noexcept : Super(pT) {} + IMPLEMENT_THOLDER_OPERATOR_EQUALS(TOwnerPtr); + IMPLEMENT_THOLDER_RVALUE_REFS(TOwnerPtr); + + T* get() noexcept + { + return Super::Get(); + } + const T* get() const noexcept + { + return Super::Get(); + } + T* release() noexcept + { + return Super::Detach(); + } + void reset(T* pT) noexcept + { + this = pT; + } private: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TOwnerPtr); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TOwnerPtr); }; /** - Manages a pointer allocated with new[] + Manages a pointer allocated with new[] */ -template< typename T > struct TArrayHelper +template +struct TArrayHelper { - static void Free(T pT) noexcept - { - delete[] pT; - } + static void Free(T pT) noexcept + { + delete[] pT; + } }; /** - Smart pointer for an array deleted with delete[] - typename T should not include the array pointer - TArrayHolder rgwz = new LPWSTR[10]; + Smart pointer for an array deleted with delete[] + typename T should not include the array pointer + TArrayHolder rgwz = new LPWSTR[10]; - Prefer to use Mso::MemoryPtr or std::vector. + Prefer to use Mso::MemoryPtr or std::vector. */ -template class TArrayHolder : public THolder> +template +class TArrayHolder : public THolder> { - typedef THolder> Super; + typedef THolder> Super; + public: - TArrayHolder() noexcept {} - /*explicit*/ TArrayHolder(T *pT) noexcept : Super(pT) {} - IMPLEMENT_THOLDER_OPERATOR_EQUALS(TArrayHolder); - IMPLEMENT_THOLDER_RVALUE_REFS(TArrayHolder); + TArrayHolder() noexcept {} + /*explicit*/ TArrayHolder(T* pT) noexcept : Super(pT) {} + IMPLEMENT_THOLDER_OPERATOR_EQUALS(TArrayHolder); + IMPLEMENT_THOLDER_RVALUE_REFS(TArrayHolder); - T* get() noexcept { return Super::Get(); } - const T* get() const noexcept { return Super::Get(); } - T* release() noexcept { return Super::Detach(); } - void reset(T* pT) noexcept { this = pT; } + T* get() noexcept + { + return Super::Get(); + } + const T* get() const noexcept + { + return Super::Get(); + } + T* release() noexcept + { + return Super::Detach(); + } + void reset(T* pT) noexcept + { + this = pT; + } private: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TArrayHolder); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TArrayHolder); }; /** - Manages a pointer cleaned up with Free() + Manages a pointer cleaned up with Free() */ -template< typename T > struct TFreeHelper +template +struct TFreeHelper { - static void Free(T pT) noexcept - { - pT->Free(); - } + static void Free(T pT) noexcept + { + pT->Free(); + } }; /** - Smart pointer for pointers deleted by calling Free() on them - typename T should not include the pointer - TOwnerIPtr pFoo( new CFoo() ); + Smart pointer for pointers deleted by calling Free() on them + typename T should not include the pointer + TOwnerIPtr pFoo( new CFoo() ); - Prefer to have a virtual destructor on your interface instead of a Free - method and use std::unique_ptr, std::shared_ptr, etc. + Prefer to have a virtual destructor on your interface instead of a Free + method and use std::unique_ptr, std::shared_ptr, etc. */ -template class TOwnerIPtr : public THolder> +template +class TOwnerIPtr : public THolder> { - typedef THolder> Super; + typedef THolder> Super; + public: - TOwnerIPtr() noexcept {} - /*explicit*/ TOwnerIPtr(T *pT) noexcept : Super(pT) {} - IMPLEMENT_THOLDER_OPERATOR_EQUALS(TOwnerIPtr); - IMPLEMENT_THOLDER_RVALUE_REFS(TOwnerIPtr); + TOwnerIPtr() noexcept {} + /*explicit*/ TOwnerIPtr(T* pT) noexcept : Super(pT) {} + IMPLEMENT_THOLDER_OPERATOR_EQUALS(TOwnerIPtr); + IMPLEMENT_THOLDER_RVALUE_REFS(TOwnerIPtr); private: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TOwnerIPtr); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TOwnerIPtr); }; /** - Manages a pointer cleaned up with Destroy() + Manages a pointer cleaned up with Destroy() */ -template struct TDestroyHelper +template +struct TDestroyHelper { - static void Free(T pT) noexcept - { - pT->Destroy(); - } + static void Free(T pT) noexcept + { + pT->Destroy(); + } }; /** - Smart pointer for pointers deleted by calling Destroy() on them - typename T should not include the pointer - Mso::TDestroyPtr pFoo( new CFoo() ); + Smart pointer for pointers deleted by calling Destroy() on them + typename T should not include the pointer + Mso::TDestroyPtr pFoo( new CFoo() ); - Prefer to have a virtual destructor on your interface instead of a Free - method and use std::unique_ptr, std::shared_ptr, etc. + Prefer to have a virtual destructor on your interface instead of a Free + method and use std::unique_ptr, std::shared_ptr, etc. */ -template class TDestroyPtr : public THolder> +template +class TDestroyPtr : public THolder> { - typedef THolder> Super; + typedef THolder> Super; + public: - TDestroyPtr() noexcept {} - explicit TDestroyPtr(T *pT) noexcept : Super(pT) {} - IMPLEMENT_THOLDER_OPERATOR_EQUALS(TDestroyPtr); - IMPLEMENT_THOLDER_RVALUE_REFS(TDestroyPtr); + TDestroyPtr() noexcept {} + explicit TDestroyPtr(T* pT) noexcept : Super(pT) {} + IMPLEMENT_THOLDER_OPERATOR_EQUALS(TDestroyPtr); + IMPLEMENT_THOLDER_RVALUE_REFS(TDestroyPtr); private: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(TDestroyPtr); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(TDestroyPtr); }; /** - Calls Finish on the resource + Calls Finish on the resource */ -template +template struct FinishHelper { - static void Free(T* pT) noexcept - { - pT->Finish(); - } + static void Free(T* pT) noexcept + { + pT->Finish(); + } }; /** - Helper that takes a function pointer + Helper that takes a function pointer */ -template< typename T, void(*pfnDeleter)(T) > +template struct TPfnHelper { - inline static void Free(T pT) noexcept - { - pfnDeleter(pT); - } + inline static void Free(T pT) noexcept + { + pfnDeleter(pT); + } }; -} // Mso +} // namespace Mso #endif // __cplusplus diff --git a/libs/smartPtr/include/object/smartPointerBase.h b/libs/smartPtr/include/object/smartPointerBase.h index 36cfa4f..91c0774 100644 --- a/libs/smartPtr/include/object/smartPointerBase.h +++ b/libs/smartPtr/include/object/smartPointerBase.h @@ -2,7 +2,7 @@ // Licensed under the MIT license. /** - Base class for all Mso Smart Pointers + Base class for all Mso Smart Pointers */ #pragma once #include @@ -12,524 +12,682 @@ #ifdef __cplusplus #pragma warning(push) -#pragma warning(disable:4996) // wmemcpy +#pragma warning(disable : 4996) // wmemcpy #include #pragma warning(pop) namespace Mso { /** - This base class manages the lifetime of various data types using a THelper - struct for resource management. It can be used with scalar and pointer - types and many strongly-typed classes have been defined later down. + This base class manages the lifetime of various data types using a THelper + struct for resource management. It can be used with scalar and pointer + types and many strongly-typed classes have been defined later down. - THelper class must define 1 method: + THelper class must define 1 method: - 1) static void Free(T pT) noexcept - this is called by the THolder class - to free the type. This will never be called with an empty value. + 1) static void Free(T pT) noexcept - this is called by the THolder class + to free the type. This will never be called with an empty value. - TEmptyTraits class can be overridden for special 'empty' behaviors. + TEmptyTraits class can be overridden for special 'empty' behaviors. */ -template < typename T, typename THelper, typename TEmptyTraits = Mso::EmptyTraits > class THolder +template > +class THolder { - using _Myt = THolder; + using _Myt = THolder; public: - using TArrowType = typename Mso::RawTraits::ArrowType; - using TAddrType = typename Mso::RawTraits::AddrType; - using TRefType = typename std::conditional, void>::value, Mso::NilType, std::remove_pointer_t>::type; + using TArrowType = typename Mso::RawTraits::ArrowType; + using TAddrType = typename Mso::RawTraits::AddrType; + using TRefType = typename std::conditional< + std::is_same, void>::value, + Mso::NilType, + std::remove_pointer_t>::type; - // TODO: consider allowing this via extension of THelper? - DECLARE_COPYCONSTR_AND_ASSIGNMENT(THolder); - -/** - Construction / Destruction -*/ - THolder() noexcept : m_pT(TEmptyTraits::EmptyVal()) {} - /*explicit*/ THolder(T pT) noexcept : m_pT(pT) {} + // TODO: consider allowing this via extension of THelper? + DECLARE_COPYCONSTR_AND_ASSIGNMENT(THolder); - __forceinline THolder( _Inout_ THolder&& rFrom ) noexcept : m_pT( rFrom.Detach() ) {} - template< typename T1 > - __forceinline THolder( _Inout_ THolder< T1, THelper, TEmptyTraits >&& rFrom ) noexcept : m_pT( rFrom.Detach() ) {} + /** + Construction / Destruction + */ + THolder() noexcept : m_pT(TEmptyTraits::EmptyVal()) {} + /*explicit*/ THolder(T pT) noexcept : m_pT(pT) {} - ~THolder() noexcept { EmptySafe(); } + __forceinline THolder(_Inout_ THolder&& rFrom) noexcept : m_pT(rFrom.Detach()) {} + template + __forceinline THolder(_Inout_ THolder&& rFrom) noexcept : m_pT(rFrom.Detach()) + { + } -/** - explicit delete owned object -*/ - void Clear() noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - if (IsEmpty()) - return; + ~THolder() noexcept + { + EmptySafe(); + } - // Using Detach ensures we don't double-free on recursion - T t = Detach(); - THelper::Free(t); - } + /** + explicit delete owned object + */ + void Clear() noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + if (IsEmpty()) + return; - // STL equivalent - void clear() noexcept { this->Clear(); } // equivalent to std::string::clear() - void reset() noexcept { this->Clear(); } // equivalent to std::unique_ptr::reset(), excpet for not supporting (yet) passing a new pointer in (like Attach here). + // Using Detach ensures we don't double-free on recursion + T t = Detach(); + THelper::Free(t); + } -/** - Empty check -*/ - bool IsEmpty() const noexcept - { - return TEmptyTraits::IsEmpty(m_pT); - } + // STL equivalent + void clear() noexcept + { + this->Clear(); + } // equivalent to std::string::clear() + void reset() noexcept + { + this->Clear(); + } // equivalent to std::unique_ptr::reset(), excpet for not supporting (yet) passing a new pointer in (like Attach + // here). + /** + Empty check + */ + bool IsEmpty() const noexcept + { + return TEmptyTraits::IsEmpty(m_pT); + } #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY - explicit operator bool() const noexcept - { - return !IsEmpty(); - } + explicit operator bool() const noexcept + { + return !IsEmpty(); + } #endif -/** - Access the contained data -*/ - T Get() const noexcept - { return m_pT; } + /** + Access the contained data + */ + T Get() const noexcept + { + return m_pT; + } - // STL equivalent - T get() const noexcept { return this->Get(); } + // STL equivalent + T get() const noexcept + { + return this->Get(); + } #ifndef MSO_THOLDER_EXPLICIT_GET_ONLY -/** - cast operator -*/ - /*_SA_deprecated_(Get)*/ operator T() const noexcept - { return m_pT; } + /** + cast operator + */ + /*_SA_deprecated_(Get)*/ operator T() const noexcept + { + return m_pT; + } #endif - - TRefType& operator[](ptrdiff_t iSubscript) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - return m_pT[iSubscript]; - } + TRefType& operator[](ptrdiff_t iSubscript) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + return m_pT[iSubscript]; + } - TArrowType operator ->() const noexcept - { - VerifyElseCrashTag(!IsEmpty(), 0x008c2697 /* tag_a9c0x */); - typedef THolder& _self; - return Mso::RawTraits::GetArrowType(const_cast<_self>(*this).m_pT); - } + TArrowType operator->() const noexcept + { + VerifyElseCrashTag(!IsEmpty(), 0x008c2697 /* tag_a9c0x */); + typedef THolder& _self; + return Mso::RawTraits::GetArrowType(const_cast<_self>(*this).m_pT); + } + const THolder& operator=(T pT) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + Clear(); + m_pT = pT; + return *this; + } - const THolder& operator=(T pT) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - Clear(); - m_pT = pT; - return *this; - } + THolder& operator=(_Inout_ THolder&& rFrom) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + // REVIEW: Do I need to check pT != m_pT? + TransferFrom(rFrom); + return *this; + } + template + THolder& operator=(_Inout_ THolder&& rFrom) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + // REVIEW: Do I need to check pT != m_pT? + TransferFrom(rFrom); + return *this; + } - THolder& operator=( _Inout_ THolder&& rFrom ) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - // REVIEW: Do I need to check pT != m_pT? - TransferFrom(rFrom); - return *this; - } + void Swap(THolder& from) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + T pT = m_pT; + m_pT = from.m_pT; + from.m_pT = pT; + } + // STL equivalent + void swap(THolder& from) noexcept + { + Swap(from); + } - template< typename T1 > - THolder& operator=( _Inout_ THolder< T1, THelper, TEmptyTraits >&& rFrom ) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - // REVIEW: Do I need to check pT != m_pT? - TransferFrom(rFrom); - return *this; - } + template + void TransferFrom(_Inout_ THolder& from) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + Attach(from.Detach()); + } + /** + take object ownership, m_pT must be empty + */ + T Place(T pT) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + AssertTag(IsEmpty(), 0x008c2698 /* tag_a9c0y */); + m_pT = pT; + return m_pT; + } - void Swap(THolder& from) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - T pT = m_pT; - m_pT = from.m_pT; - from.m_pT = pT; - } + /** + take object ownership, deletes previously owned object if any + */ + T Attach(T pT) noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + Clear(); + return Place(pT); + } - // STL equivalent - void swap(THolder& from) noexcept { Swap(from); } + /** + release ownership without deleting object + */ + T Detach() noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + T pT = m_pT; + TEmptyTraits::Empty(m_pT); + return pT; + } - template< typename T1, typename THelper1, typename TEmptyTraits1 > void TransferFrom(_Inout_ THolder< T1, THelper1, TEmptyTraits1 >& from) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - Attach(from.Detach()); - } - -/** - take object ownership, m_pT must be empty -*/ - T Place(T pT) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - AssertTag(IsEmpty(), 0x008c2698 /* tag_a9c0y */); - m_pT = pT; - return m_pT; - } - -/** - take object ownership, deletes previously owned object if any -*/ - T Attach(T pT) noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - Clear(); - return Place(pT); - } - -/** - release ownership without deleting object -*/ - T Detach() noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - T pT = m_pT; - TEmptyTraits::Empty(m_pT); - return pT; - } - - // STL equivalent - T release() noexcept { return this->Detach(); } // equivalent to std::unique_ptr::release() + // STL equivalent + T release() noexcept + { + return this->Detach(); + } // equivalent to std::unique_ptr::release() #ifndef MSO_THOLDER_NO_ADDR_OPERATOR -/** - & operator to retrieve object, THolder must be empty -*/ - TAddrType operator&() noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - AssertTag(IsEmpty(), 0x008c2699 /* tag_a9c0z */); - return &m_pT; - } + /** + & operator to retrieve object, THolder must be empty + */ + TAddrType operator&() noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + AssertTag(IsEmpty(), 0x008c2699 /* tag_a9c0z */); + return &m_pT; + } #endif // !MSO_THOLDER_NO_ADDR_OPERATOR -/** - Retrieves the address of the object. Asserts that THolder is empty. + /** + Retrieves the address of the object. Asserts that THolder is empty. - void GetSomething(T** ppT); - - Mso::THolder pT; - GetSomething(pT.GetAddressOf()); + void GetSomething(T** ppT); - ClearAndGetAddressOf() will ensure any existing object is cleared first. - GetRaw() avoids the assert if you need the address of an existing object. -*/ - TAddrType GetAddressOf() noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - AssertSzTag(IsEmpty(), "Getting the address of an existing object? This usually leads to a leak.", 0x008c269a /* tag_a9c00 */); - return GetRaw(); - } + Mso::THolder pT; + GetSomething(pT.GetAddressOf()); + ClearAndGetAddressOf() will ensure any existing object is cleared first. + GetRaw() avoids the assert if you need the address of an existing object. + */ + TAddrType GetAddressOf() noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + AssertSzTag( + IsEmpty(), + "Getting the address of an existing object? This usually leads to a leak.", + 0x008c269a /* tag_a9c00 */); + return GetRaw(); + } - TAddrType ClearAndGetAddressOf() noexcept - { - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - Clear(); - return GetRaw(); - } + TAddrType ClearAndGetAddressOf() noexcept + { + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + Clear(); + return GetRaw(); + } + TAddrType GetRaw() noexcept + { + // This is dangerous so you better know what you are doing + static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); + return &m_pT; + } - TAddrType GetRaw() noexcept - { - // This is dangerous so you better know what you are doing - static_assert(!Mso::RawTraits::isReference, "Not allowed when T is a reference type"); - return &m_pT; - } + /** + Sometimes the pointer to the actual THolder is needed + */ + const THolder* GetThis() const noexcept + { + return this; + } + THolder* GetThis() noexcept + { + return this; + } -/** - Sometimes the pointer to the actual THolder is needed -*/ - const THolder* GetThis() const noexcept { return this; } - THolder* GetThis() noexcept { return this; } - -/** - Deprecated APIs to remove over time. -*/ - /*_SA_deprecated_(Clear)*/ void Empty() noexcept { Clear(); } - /*_SA_deprecated_(Clear)*/ void Free() noexcept { Clear(); } - /*_SA_deprecated_(Clear)*/ void Close() noexcept { Clear(); } - /*_SA_deprecated_(Clear)*/ void Release() noexcept { Clear(); } - /*_SA_deprecated_(IsEmpty)*/ bool FIsEmpty() const noexcept { return IsEmpty(); } - /*_SA_deprecated_(Detach)*/ T Extract() noexcept { return Detach(); } - template< typename T1 > - /*_SA_deprecated_(TransferFrom)*/ void Transfer(THolder< T1, THelper, TEmptyTraits >& from) noexcept { return TransferFrom( from ); } - /*_SA_deprecated_(GetAddressOf)*/ TAddrType Ptr() noexcept { return this->GetAddressOf(); } - /*_SA_deprecated_(ClearAndGetAddressOf)*/ TAddrType Address() noexcept { return this->ClearAndGetAddressOf(); } + /** + Deprecated APIs to remove over time. + */ + /*_SA_deprecated_(Clear)*/ void Empty() noexcept + { + Clear(); + } + /*_SA_deprecated_(Clear)*/ void Free() noexcept + { + Clear(); + } + /*_SA_deprecated_(Clear)*/ void Close() noexcept + { + Clear(); + } + /*_SA_deprecated_(Clear)*/ void Release() noexcept + { + Clear(); + } + /*_SA_deprecated_(IsEmpty)*/ bool FIsEmpty() const noexcept + { + return IsEmpty(); + } + /*_SA_deprecated_(Detach)*/ T Extract() noexcept + { + return Detach(); + } + template + /*_SA_deprecated_(TransferFrom)*/ void Transfer(THolder& from) noexcept + { + return TransferFrom(from); + } + /*_SA_deprecated_(GetAddressOf)*/ TAddrType Ptr() noexcept + { + return this->GetAddressOf(); + } + /*_SA_deprecated_(ClearAndGetAddressOf)*/ TAddrType Address() noexcept + { + return this->ClearAndGetAddressOf(); + } protected: - T m_pT; + T m_pT; private: - // Handles cases where T is a reference type - must not be exposed to clients. - void EmptySafe() noexcept - { - if (IsEmpty()) - return; + // Handles cases where T is a reference type - must not be exposed to clients. + void EmptySafe() noexcept + { + if (IsEmpty()) + return; - T pT = m_pT; + T pT = m_pT; #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#pragma warning(suppress:4996) // deprecated function - TEmptyTraits::UnsafeEmpty(m_pT); +#pragma warning(suppress : 4996) // deprecated function + TEmptyTraits::UnsafeEmpty(m_pT); #if defined(__clang__) #pragma clang diagnostic pop #endif - THelper::Free(pT); - } + THelper::Free(pT); + } - // TODO: consider allowing this via extension of THelper? - template< typename T1 > const THolder& operator=( const THolder< T1, THelper, TEmptyTraits >& from ); + // TODO: consider allowing this via extension of THelper? + template + const THolder& operator=(const THolder& from); - // Can't mix helpers - template< typename T1, typename THelper1, typename TEmptyTraits1 > const THolder& operator=( const THolder< T1, THelper1, TEmptyTraits1 >& from ); - template< typename T1, typename THelper1, typename TEmptyTraits1 > THolder& operator=( _Inout_ THolder< T1, THelper1, TEmptyTraits1 >&& rFrom ); - template< typename T1, typename THelper1, typename TEmptyTraits1 > void Place ( const THolder< T1, THelper1, TEmptyTraits1 >& ); - template< typename T1, typename THelper1, typename TEmptyTraits1 > void Attach( const THolder< T1, THelper1, TEmptyTraits1 >& ); - template< typename T1, typename THelper1, typename TEmptyTraits1 > void Transfer( const THolder< T1, THelper1, TEmptyTraits1 >& ); + // Can't mix helpers + template + const THolder& operator=(const THolder& from); + template + THolder& operator=(_Inout_ THolder&& rFrom); + template + void Place(const THolder&); + template + void Attach(const THolder&); + template + void Transfer(const THolder&); - // Improper usage - template< typename T1 > void Place ( const THolder< T1, THelper, TEmptyTraits >& ); // use Transfer - template< typename T1 > void Attach( const THolder< T1, THelper, TEmptyTraits >& ); // use Transfer + // Improper usage + template + void Place(const THolder&); // use Transfer + template + void Attach(const THolder&); // use Transfer }; // class THolder #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY /** - Operators for THolder + Operators for THolder */ -template +template < + typename T1, + typename THelper1, + typename TEmptyTraits1, + typename T2, + typename THelper2, + typename TEmptyTraits2> bool operator==(const THolder& a, const THolder& b) noexcept { - return a.Get() == b.Get(); + return a.Get() == b.Get(); } -template +template bool operator==(const THolder& a, decltype(__nullptr)) noexcept { - return a.Get() == nullptr; + return a.Get() == nullptr; } -template +template bool operator==(decltype(__nullptr), const THolder& a) noexcept { - return a.Get() == nullptr; + return a.Get() == nullptr; } -template +template < + typename T1, + typename THelper1, + typename TEmptyTraits1, + typename T2, + typename THelper2, + typename TEmptyTraits2> bool operator!=(const THolder& a, const THolder& b) noexcept { - return a.Get() != b.Get(); + return a.Get() != b.Get(); } -template +template bool operator!=(const THolder& a, decltype(__nullptr)) noexcept { - return a.Get() != nullptr; + return a.Get() != nullptr; } -template +template bool operator!=(decltype(__nullptr), const THolder& a) noexcept { - return a.Get() != nullptr; + return a.Get() != nullptr; } #endif // MSO_THOLDER_EXPLICIT_GET_ONLY /** - Macros to implement a few basic THolder methods in derived classes. + Macros to implement a few basic THolder methods in derived classes. */ /** - Helper to define operator= in derived classes + Helper to define operator= in derived classes */ -#define IMPLEMENT_THOLDER_OPERATOR_EQUALS(T) \ - template< typename T1 > const T& operator=(_In_opt_ T1 pT) noexcept { Super::operator=(pT); return *this; } +#define IMPLEMENT_THOLDER_OPERATOR_EQUALS(T) \ + template \ + const T& operator=(_In_opt_ T1 pT) noexcept \ + { \ + Super::operator=(pT); \ + return *this; \ + } /** - Helper to add RVALUE methods to derived THolder classes + Helper to add RVALUE methods to derived THolder classes */ -#define IMPLEMENT_THOLDER_RVALUE_REFS_(T, TBase) \ - T( _Inout_ T&& rFrom ) noexcept : TBase(std::forward(rFrom)) {} \ - T& operator=( _Inout_ T&& rFrom ) noexcept { this->TransferFrom(rFrom); return *this; } +#define IMPLEMENT_THOLDER_RVALUE_REFS_(T, TBase) \ + T(_Inout_ T&& rFrom) noexcept : TBase(std::forward(rFrom)) {} \ + T& operator=(_Inout_ T&& rFrom) noexcept \ + { \ + this->TransferFrom(rFrom); \ + return *this; \ + } #define IMPLEMENT_THOLDER_RVALUE_REFS(T) IMPLEMENT_THOLDER_RVALUE_REFS_(T, Super) /** - Try to prevent mixing up constructors + Try to prevent mixing up constructors */ #define PREVENT_MISMATCH_THOLDER_CONSTRUCTORS(T) \ - template< typename T1, typename THelper > T(const THolder< T1, THelper > &ref) noexcept; + template \ + T(const THolder& ref) \ + noexcept; /** - In some cases, additional data must be stored with the held object. - THolderPair supports this. Note that no requirements are placed on the - associated data although using a pointer type is strongly encouraged. + In some cases, additional data must be stored with the held object. + THolderPair supports this. Note that no requirements are placed on the + associated data although using a pointer type is strongly encouraged. */ /** - THolderPairData stores a type and associated data + THolderPairData stores a type and associated data */ -template struct THolderPairData +template +struct THolderPairData { public: - operator T() const noexcept - { return pT; } - T operator ->() const noexcept - { VerifyElseCrashTag(pT != nullptr, 0x008c288a /* tag_a9c8k */); return pT; } - bool operator==(const THolderPairData& other) const - { return (pT == other.pT && pData == other.pData); } - bool operator!=(const THolderPairData& other) const - { return !(*this == other); } + operator T() const noexcept + { + return pT; + } + T operator->() const noexcept + { + VerifyElseCrashTag(pT != nullptr, 0x008c288a /* tag_a9c8k */); + return pT; + } + bool operator==(const THolderPairData& other) const + { + return (pT == other.pT && pData == other.pData); + } + bool operator!=(const THolderPairData& other) const + { + return !(*this == other); + } - T pT; - TData pData; + T pT; + TData pData; }; /** - EmptyTraits for the THolderPairData + EmptyTraits for the THolderPairData */ -template< typename S, typename SData > +template struct EmptyTraits> - { - static THolderPairData EmptyVal() noexcept { THolderPairData sEmpty = {0}; return sEmpty; } - static bool IsEmpty(const THolderPairData& t) noexcept { return Mso::EmptyTraits::IsEmpty(t.pT); } - static void Empty(THolderPairData& t) noexcept { Mso::EmptyTraits::Empty(t.pT); Mso::EmptyTraits::Empty(t.pData); } - __declspec(deprecated) static void UnsafeEmpty(THolderPairData& t) noexcept { Empty(t); } - }; +{ + static THolderPairData EmptyVal() noexcept + { + THolderPairData sEmpty = {0}; + return sEmpty; + } + static bool IsEmpty(const THolderPairData& t) noexcept + { + return Mso::EmptyTraits::IsEmpty(t.pT); + } + static void Empty(THolderPairData& t) noexcept + { + Mso::EmptyTraits::Empty(t.pT); + Mso::EmptyTraits::Empty(t.pData); + } + __declspec(deprecated) static void UnsafeEmpty(THolderPairData& t) noexcept + { + Empty(t); + } +}; /** - Smart pointer for holding a pair of data objects. - typename T must be a pointer types - Private THolder derivation avoids confusion to consumers. + Smart pointer for holding a pair of data objects. + typename T must be a pointer types + Private THolder derivation avoids confusion to consumers. */ -template class THolderPair : protected THolder, THelper> +template +class THolderPair : protected THolder, THelper> { - using _Myt = THolderPair; + using _Myt = THolderPair; public: - DECLARE_COPYCONSTR_AND_ASSIGNMENT(THolderPair); + DECLARE_COPYCONSTR_AND_ASSIGNMENT(THolderPair); - using Super = THolder, THelper>; - using TRefType = typename std::conditional, void>::value, Mso::NilType, std::remove_pointer_t>::type; + using Super = THolder, THelper>; + using TRefType = typename std:: + conditional, void>::value, Mso::NilType, std::remove_pointer_t>::type; - THolderPair() noexcept {} - explicit THolderPair(T pT, _In_opt_ TData pData) noexcept { Attach(pT, pData); } - THolderPair(_Inout_ THolderPair&& rFrom) noexcept : Super(std::forward(rFrom)) {} - THolderPair& operator=(_Inout_ T&& rFrom) noexcept { TransferFrom(rFrom); return *this; } + THolderPair() noexcept {} + explicit THolderPair(T pT, _In_opt_ TData pData) noexcept + { + Attach(pT, pData); + } + THolderPair(_Inout_ THolderPair&& rFrom) noexcept : Super(std::forward(rFrom)) {} + THolderPair& operator=(_Inout_ T&& rFrom) noexcept + { + TransferFrom(rFrom); + return *this; + } -/** - Promote basic methods from the base class -*/ - void Clear() noexcept { return Super::Clear(); } - void clear() noexcept { return Super::Clear(); } - bool IsEmpty() const noexcept { return Super::IsEmpty(); } + /** + Promote basic methods from the base class + */ + void Clear() noexcept + { + return Super::Clear(); + } + void clear() noexcept + { + return Super::Clear(); + } + bool IsEmpty() const noexcept + { + return Super::IsEmpty(); + } - T Get() const noexcept { return Super::Get(); } - T get() const noexcept { return Super::get(); } + T Get() const noexcept + { + return Super::Get(); + } + T get() const noexcept + { + return Super::get(); + } #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY - explicit operator bool() const noexcept { return Super::operator bool(); } + explicit operator bool() const noexcept + { + return Super::operator bool(); + } #else - /*_SA_deprecated_(Get)*/ operator T() const noexcept { return Get(); } + /*_SA_deprecated_(Get)*/ operator T() const noexcept + { + return Get(); + } #endif - TRefType& operator[](ptrdiff_t iSubscript) noexcept { return Super::Get()[iSubscript]; } - T operator ->() const noexcept { return Super::operator ->(); } + TRefType& operator[](ptrdiff_t iSubscript) noexcept + { + return Super::Get()[iSubscript]; + } + T operator->() const noexcept + { + return Super::operator->(); + } - void Swap(THolderPair& from ) noexcept { return Super::Swap(from); } - T Place(T pT, _In_opt_ TData pData) noexcept - { - THolderPairData pair = { pT, pData }; - return Super::Place(pair); - } + void Swap(THolderPair& from) noexcept + { + return Super::Swap(from); + } + T Place(T pT, _In_opt_ TData pData) noexcept + { + THolderPairData pair = {pT, pData}; + return Super::Place(pair); + } - void Attach(T pT, _In_opt_ TData pData) noexcept - { - THolderPairData pair = { pT, pData }; - Super::Attach(pair); - } - - T Detach(_Out_opt_ TData* pDataOut = nullptr) noexcept - { - if (pDataOut != nullptr) - *pDataOut = this->m_pT.pData; - return Super::Detach(); - } + void Attach(T pT, _In_opt_ TData pData) noexcept + { + THolderPairData pair = {pT, pData}; + Super::Attach(pair); + } - T* GetAddressOf(_In_opt_ TData pData) noexcept - { - AssertSzTag(IsEmpty(), "Getting the address of an existing object? This usually leads to a leak.", 0x008c269c /* tag_a9c02 */); - this->m_pT.pData = pData; - return &this->m_pT.pT; - } + T Detach(_Out_opt_ TData* pDataOut = nullptr) noexcept + { + if (pDataOut != nullptr) + *pDataOut = this->m_pT.pData; + return Super::Detach(); + } - T* ClearAndGetAddressOf(_In_opt_ TData pData) noexcept - { - Clear(); - return GetAddressOf(pData); - } + T* GetAddressOf(_In_opt_ TData pData) noexcept + { + AssertSzTag( + IsEmpty(), + "Getting the address of an existing object? This usually leads to a leak.", + 0x008c269c /* tag_a9c02 */); + this->m_pT.pData = pData; + return &this->m_pT.pT; + } -/** - GetData provides access to the data pair. -*/ - TData GetData() const noexcept { return this->m_pT.pData; } + T* ClearAndGetAddressOf(_In_opt_ TData pData) noexcept + { + Clear(); + return GetAddressOf(pData); + } + /** + GetData provides access to the data pair. + */ + TData GetData() const noexcept + { + return this->m_pT.pData; + } - /*_SA_deprecated_(Clear)*/ void Empty() noexcept { return Super::Clear(); } + /*_SA_deprecated_(Clear)*/ void Empty() noexcept + { + return Super::Clear(); + } }; - #ifdef MSO_THOLDER_EXPLICIT_GET_ONLY /** - Operators for THolderPair + Operators for THolderPair */ -template +template bool operator==(const THolderPair& a, const THolderPair& b) noexcept { - return a.Get() == b.Get(); + return a.Get() == b.Get(); } -template +template bool operator==(const THolderPair& a, decltype(__nullptr)) noexcept { - return a.Get() == nullptr; + return a.Get() == nullptr; } -template +template bool operator==(decltype(__nullptr), const THolderPair& a) noexcept { - return a.Get() == nullptr; + return a.Get() == nullptr; } -template +template bool operator!=(const THolderPair& a, const THolderPair& b) noexcept { - return a.Get() != b.Get(); + return a.Get() != b.Get(); } -template +template bool operator!=(const THolderPair& a, decltype(__nullptr)) noexcept { - return a.Get() != nullptr; + return a.Get() != nullptr; } -template +template bool operator!=(decltype(__nullptr), const THolderPair& a) noexcept { - return a.Get() != nullptr; + return a.Get() != nullptr; } #endif // MSO_THOLDER_EXPLICIT_GET_ONLY -} // end Mso namespace +} // namespace Mso #endif // __cplusplus - diff --git a/libs/tagUtils/include/tagUtils/tagTypes.h b/libs/tagUtils/include/tagUtils/tagTypes.h index 206432a..b9c624b 100644 --- a/libs/tagUtils/include/tagUtils/tagTypes.h +++ b/libs/tagUtils/include/tagUtils/tagTypes.h @@ -15,29 +15,29 @@ constexpr unsigned int UNTAGGED = static_cast(0x0000); class MsoReserveTag final { public: - /** - * Creates a tag from underlying value. - * @param v the value of the tag. - * Note that the expression evaluating to v should be a literal or simple variable expression; - * more complex expressions may cause the tagging script to fail. - * See http://aka.ms/officetagging for more details on the tagging script. - */ - constexpr explicit MsoReserveTag(unsigned int v) noexcept : m_value(v) {} + /** + * Creates a tag from underlying value. + * @param v the value of the tag. + * Note that the expression evaluating to v should be a literal or simple variable expression; + * more complex expressions may cause the tagging script to fail. + * See http://aka.ms/officetagging for more details on the tagging script. + */ + constexpr explicit MsoReserveTag(unsigned int v) noexcept : m_value(v) {} - // This is an unfortunate work around at the moment to allow conversion back to the underlying - // type so that existing comparisons and function signatures work - constexpr operator unsigned int() const noexcept - { - return m_value; - } + // This is an unfortunate work around at the moment to allow conversion back to the underlying + // type so that existing comparisons and function signatures work + constexpr operator unsigned int() const noexcept + { + return m_value; + } private: - const unsigned int m_value; + const unsigned int m_value; }; constexpr inline MsoReserveTag MsoReserve() noexcept { - return MsoReserveTag(UNTAGGED); + return MsoReserveTag(UNTAGGED); } #else diff --git a/libs/tagUtils/include/tagUtils/tagUtils.h b/libs/tagUtils/include/tagUtils/tagUtils.h index c24fea5..1cba74a 100644 --- a/libs/tagUtils/include/tagUtils/tagUtils.h +++ b/libs/tagUtils/include/tagUtils/tagUtils.h @@ -3,7 +3,7 @@ /* * Utility methods for converting tag string to integer value and vice versa -*/ + */ #pragma once #ifndef LIBLET_TAGUTILS_TAGUTILS_H @@ -18,334 +18,341 @@ #ifdef __cplusplus /** - MAX_TAG_CCH denotes the maximum tag string buffer size, including null termination. + MAX_TAG_CCH denotes the maximum tag string buffer size, including null termination. */ const uint32_t MAX_TAG_CCH = 6; -namespace TaggingUtilities +namespace TaggingUtilities { +namespace details { +template +struct SymbolSpace { - namespace details - { - template - struct SymbolSpace - { - const T lowAlpha; - const T highAlpha; - const T lowDecimal; - const T highDecimal; - T const * const empty = nullptr; - T const value[1] = "*"; - }; - - template<> - struct SymbolSpace - { - SymbolSpace() noexcept {}; - SymbolSpace& operator=(const SymbolSpace&) = delete; - - const char lowAlpha = 'a'; - const char highAlpha ='z'; - const char lowDecimal = '0'; - const char highDecimal = '9'; - char const * const empty = "00000"; - char const value[65] = "abcdefghijklmnopqrstuvwxyz0123456789****************************"; - }; - - template<> - struct SymbolSpace - { - SymbolSpace() noexcept {}; - SymbolSpace& operator=(const SymbolSpace&) = delete; - - const wchar_t lowAlpha = L'a'; - const wchar_t highAlpha = L'z'; - const wchar_t lowDecimal = L'0'; - const wchar_t highDecimal = L'9'; - wchar_t const * const empty = L"00000"; - wchar_t const value[65] = L"abcdefghijklmnopqrstuvwxyz0123456789****************************"; - }; - - template<> - struct SymbolSpace - { - SymbolSpace() noexcept {}; - SymbolSpace& operator=(const SymbolSpace&) = delete; - - const char16_t lowAlpha = u'a'; - const char16_t highAlpha = u'z'; - const char16_t lowDecimal = u'0'; - const char16_t highDecimal = u'9'; - char16_t const * const empty = u"00000"; - char16_t const value[65] = u"abcdefghijklmnopqrstuvwxyz0123456789****************************"; - }; - - template<> - struct SymbolSpace - { - SymbolSpace() noexcept {}; - SymbolSpace& operator=(const SymbolSpace&) = delete; - - const char32_t lowAlpha = U'a'; - const char32_t highAlpha = U'z'; - const char32_t lowDecimal = U'0'; - const char32_t highDecimal = U'9'; - char32_t const * const empty = U"00000"; - char32_t const value[65] = U"abcdefghijklmnopqrstuvwxyz0123456789****************************"; - }; - - template - static T TagLetterConvertValue(T character) noexcept - { - static const SymbolSpace ss; - - //a-z - if(character >= ss.lowAlpha && character <= ss.highAlpha) - return static_cast(character - ss.lowAlpha); - //0-9: 0 is at index 26 in details::m_szSymbolSpace. (z - a) + 1 = (122 - 97) + 1 = 26 - if(character >= ss.lowDecimal && character <= ss.highDecimal) - return static_cast(character - ss.lowDecimal + (ss.highAlpha - ss.lowAlpha) + 1); - - //should not be calling with characters that are not a-z or 0-9, if they do give it back to them - return character; - } - - - static const int m_iMaxNumericTag = 0x0000FFFF; - static const int m_iMinOldSchemeHighByteValue = 36; - - inline bool IsUntagged(uint32_t value) noexcept - { - return (value == 0 || value == UNTAGGED); - } - } - - template - _Success_(return == true) bool NumericTagToString(uint32_t iTag, _Out_z_cap_c_(MAX_TAG_CCH) T *result) noexcept - { - using ss = details::SymbolSpace; - ss symbol_space; - const T* digit_space = symbol_space.value + 26; - - int insertDigit = 0; - for (int maxDigit = 0; maxDigit < 5; ++maxDigit) - { - const uint32_t place = static_cast(pow(10, (4 - maxDigit))); - const uint32_t digit = iTag / place; - if (iTag == 0 || digit || insertDigit) - { - iTag -= (place * digit); - result[insertDigit] = digit_space[digit]; - ++insertDigit; - } - } - result[insertDigit] = 0; - - return true; - } - - template - _Success_(return == true) bool FourCharTagToString(uint32_t iTag, _Out_z_cap_c_(MAX_TAG_CCH) T *result) noexcept - { - result[0] = static_cast((iTag >> 24) & 0xFF); - result[1] = static_cast((iTag >> 16) & 0xFF); - result[2] = static_cast((iTag >> 8) & 0xFF); - result[3] = static_cast((iTag)& 0xFF); - result[4] = 0; - return true; - } - - template - _Success_(return == true) bool FiveCharTagToString(uint32_t iTag, _Out_z_cap_c_(MAX_TAG_CCH) T *result) noexcept - { - using ss = details::SymbolSpace; - ss symbol_space; - result[0] = symbol_space.value[(iTag >> 24) & 0x3F]; - result[1] = symbol_space.value[(iTag >> 18) & 0x3F]; - result[2] = symbol_space.value[(iTag >> 12) & 0x3F]; - result[3] = symbol_space.value[(iTag >> 6) & 0x3F]; - result[4] = symbol_space.value[(iTag)& 0x3F]; - result[5] = 0; - return true; - } - - template - _Success_(return == true) bool ConvertTagToStringInternal(uint32_t iTag, _Out_z_cap_(cch) T *result, size_t cch) noexcept - { - if (cch < MAX_TAG_CCH || result == nullptr) - { - return false; - } - - if (iTag <= details::m_iMaxNumericTag) - { - return NumericTagToString(iTag, result); - } - - if ((iTag >> 24) >= details::m_iMinOldSchemeHighByteValue) - { - return FourCharTagToString(iTag, result); - } - - return FiveCharTagToString(iTag, result); - } - - /** - Converts integer tag into equivalent string - */ - inline bool ConvertiTagToSzTag(uint32_t iTag, _Out_z_cap_(iBufSize) char *result, size_t iBufSize) noexcept - { - return ConvertTagToStringInternal(iTag, result, iBufSize); - } - - /** - Converts integer tag into equivalent wstring - */ - inline bool ConvertiTagToWzTag(uint32_t iTag, _Out_z_cap_(iBufSize) wchar_t *result, size_t iBufSize) noexcept - { - return ConvertTagToStringInternal(iTag, result, iBufSize); - } - - /** - ConvertTagToString can be used with fixed buffers. - Use ConvertiTagTo[Sz|Wz]Tag for non-fixed buffers. - - wchar_t wzTag[MAX_TAG_CCH]; - ConvertTagToString(tag, wzTag); - */ - template inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ char (&szOut)[cch]) noexcept - { - static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); - (void) ConvertiTagToSzTag(iTag, szOut, cch); - } - - template inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ wchar_t (&wzOut)[cch]) noexcept - { - static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); - (void) ConvertiTagToWzTag(iTag, wzOut, cch); - } - - template inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ char16_t (&wzOut)[cch]) noexcept - { - static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); - (void) ConvertTagToStringInternal(iTag, wzOut, cch); - } - - template inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ char32_t (&wzOut)[cch]) noexcept - { - static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); - (void) ConvertTagToStringInternal(iTag, wzOut, cch); - } - - - /** - Converts character buffer to integer tag - */ - template - inline uint32_t ConvertStringToTagInternal(_In_count_(cch) const T* wz, size_t cch) noexcept - { - if(4 == cch) - { - return static_cast((wz[0]<<24) | (wz[1]<<16) | (wz[2]<<8) | wz[3]); - } - - if(5 == cch) - { - return static_cast(((((((((details::TagLetterConvertValue(wz[0])) <<6) + - details::TagLetterConvertValue(wz[1]))<<6) + - details::TagLetterConvertValue(wz[2]))<<6) + - details::TagLetterConvertValue(wz[3]))<<6) + - details::TagLetterConvertValue(wz[4])); - } - - return 0; - } - - inline uint32_t ConvertStringToTag(_In_count_(cch) const wchar_t* wz, size_t cch) noexcept - { - return ConvertStringToTagInternal(wz, cch); - } - - inline uint32_t ConvertStringToTag(_In_count_(cch) const char* wz, size_t cch) noexcept - { - return ConvertStringToTagInternal(wz, cch); - } - - inline uint32_t ConvertStringToTag(_In_count_(cch) const char16_t* wz, size_t cch) noexcept - { - return ConvertStringToTagInternal(wz, cch); - } - - inline uint32_t ConvertStringToTag(_In_count_(cch) const char32_t* wz, size_t cch) noexcept - { - return ConvertStringToTagInternal(wz, cch); - } - - /** - Converts character buffer to integer tag inferring the buffer size - */ - template - inline uint32_t ConvertStringToTag(T (&wzOut)[cch]) noexcept - { - static_assert(cch > 0, "No point in converting a zero sized buffer"); - static_assert(cch <= MAX_TAG_CCH, "No parsed buffer should be greater than MAX_TAG_CCH"); - // inferring the size assumes that the string in the buffer is null terminated so we - // ignore the last character since this is the equivalent of what strlen/wcslen do - return ConvertStringToTag(wzOut, cch-1); - } - - /** - A RAII holder converting a tag value into a string - */ - template - class TagHolder - { - public: - /** - @param tag value - @param bool value indicating whether or not untagged values should result in an empty string - */ - TagHolder(uint32_t iTag, bool formatZero) noexcept - { - if(!formatZero && details::IsUntagged(iTag)) - return; - - ConvertTagToString(iTag, m_szTag); - } - - /** - @param tag value - */ - TagHolder(uint32_t iTag) noexcept : TagHolder(iTag, true) - { - } - - /** - @return a pointer to a null-terminated character buffer - @deprecated prefer c_str() instead - */ - _Ret_z_ T const * const GetPCWSTR() const noexcept - { return this->c_str(); } - - /** - @return a pointer to a null-terminated character buffer - */ - _Ret_z_ T const * const c_str() const noexcept - { return m_szTag; } - - /** - @return a pointer to a null-terminated character buffer - */ - _Ret_z_ operator T const * const() const noexcept - { return this->c_str(); } - - private: - T m_szTag[MAX_TAG_CCH] = {0}; - }; - - using WzTag = TagHolder; - using SzTag = TagHolder; + const T lowAlpha; + const T highAlpha; + const T lowDecimal; + const T highDecimal; + T const* const empty = nullptr; + T const value[1] = "*"; }; +template <> +struct SymbolSpace +{ + SymbolSpace() noexcept {}; + SymbolSpace& operator=(const SymbolSpace&) = delete; + + const char lowAlpha = 'a'; + const char highAlpha = 'z'; + const char lowDecimal = '0'; + const char highDecimal = '9'; + char const* const empty = "00000"; + char const value[65] = "abcdefghijklmnopqrstuvwxyz0123456789****************************"; +}; + +template <> +struct SymbolSpace +{ + SymbolSpace() noexcept {}; + SymbolSpace& operator=(const SymbolSpace&) = delete; + + const wchar_t lowAlpha = L'a'; + const wchar_t highAlpha = L'z'; + const wchar_t lowDecimal = L'0'; + const wchar_t highDecimal = L'9'; + wchar_t const* const empty = L"00000"; + wchar_t const value[65] = L"abcdefghijklmnopqrstuvwxyz0123456789****************************"; +}; + +template <> +struct SymbolSpace +{ + SymbolSpace() noexcept {}; + SymbolSpace& operator=(const SymbolSpace&) = delete; + + const char16_t lowAlpha = u'a'; + const char16_t highAlpha = u'z'; + const char16_t lowDecimal = u'0'; + const char16_t highDecimal = u'9'; + char16_t const* const empty = u"00000"; + char16_t const value[65] = u"abcdefghijklmnopqrstuvwxyz0123456789****************************"; +}; + +template <> +struct SymbolSpace +{ + SymbolSpace() noexcept {}; + SymbolSpace& operator=(const SymbolSpace&) = delete; + + const char32_t lowAlpha = U'a'; + const char32_t highAlpha = U'z'; + const char32_t lowDecimal = U'0'; + const char32_t highDecimal = U'9'; + char32_t const* const empty = U"00000"; + char32_t const value[65] = U"abcdefghijklmnopqrstuvwxyz0123456789****************************"; +}; + +template +static T TagLetterConvertValue(T character) noexcept +{ + static const SymbolSpace ss; + + // a-z + if (character >= ss.lowAlpha && character <= ss.highAlpha) + return static_cast(character - ss.lowAlpha); + // 0-9: 0 is at index 26 in details::m_szSymbolSpace. (z - a) + 1 = (122 - 97) + 1 = 26 + if (character >= ss.lowDecimal && character <= ss.highDecimal) + return static_cast(character - ss.lowDecimal + (ss.highAlpha - ss.lowAlpha) + 1); + + // should not be calling with characters that are not a-z or 0-9, if they do give it back to them + return character; +} + +static const int m_iMaxNumericTag = 0x0000FFFF; +static const int m_iMinOldSchemeHighByteValue = 36; + +inline bool IsUntagged(uint32_t value) noexcept +{ + return (value == 0 || value == UNTAGGED); +} +} // namespace details + +template +_Success_(return == true) bool NumericTagToString(uint32_t iTag, _Out_z_cap_c_(MAX_TAG_CCH) T* result) noexcept +{ + using ss = details::SymbolSpace; + ss symbol_space; + const T* digit_space = symbol_space.value + 26; + + int insertDigit = 0; + for (int maxDigit = 0; maxDigit < 5; ++maxDigit) + { + const uint32_t place = static_cast(pow(10, (4 - maxDigit))); + const uint32_t digit = iTag / place; + if (iTag == 0 || digit || insertDigit) + { + iTag -= (place * digit); + result[insertDigit] = digit_space[digit]; + ++insertDigit; + } + } + result[insertDigit] = 0; + + return true; +} + +template +_Success_(return == true) bool FourCharTagToString(uint32_t iTag, _Out_z_cap_c_(MAX_TAG_CCH) T* result) noexcept +{ + result[0] = static_cast((iTag >> 24) & 0xFF); + result[1] = static_cast((iTag >> 16) & 0xFF); + result[2] = static_cast((iTag >> 8) & 0xFF); + result[3] = static_cast((iTag)&0xFF); + result[4] = 0; + return true; +} + +template +_Success_(return == true) bool FiveCharTagToString(uint32_t iTag, _Out_z_cap_c_(MAX_TAG_CCH) T* result) noexcept +{ + using ss = details::SymbolSpace; + ss symbol_space; + result[0] = symbol_space.value[(iTag >> 24) & 0x3F]; + result[1] = symbol_space.value[(iTag >> 18) & 0x3F]; + result[2] = symbol_space.value[(iTag >> 12) & 0x3F]; + result[3] = symbol_space.value[(iTag >> 6) & 0x3F]; + result[4] = symbol_space.value[(iTag)&0x3F]; + result[5] = 0; + return true; +} + +template +_Success_(return + == true) bool ConvertTagToStringInternal(uint32_t iTag, _Out_z_cap_(cch) T* result, size_t cch) noexcept +{ + if (cch < MAX_TAG_CCH || result == nullptr) + { + return false; + } + + if (iTag <= details::m_iMaxNumericTag) + { + return NumericTagToString(iTag, result); + } + + if ((iTag >> 24) >= details::m_iMinOldSchemeHighByteValue) + { + return FourCharTagToString(iTag, result); + } + + return FiveCharTagToString(iTag, result); +} + +/** + Converts integer tag into equivalent string +*/ +inline bool ConvertiTagToSzTag(uint32_t iTag, _Out_z_cap_(iBufSize) char* result, size_t iBufSize) noexcept +{ + return ConvertTagToStringInternal(iTag, result, iBufSize); +} + +/** + Converts integer tag into equivalent wstring +*/ +inline bool ConvertiTagToWzTag(uint32_t iTag, _Out_z_cap_(iBufSize) wchar_t* result, size_t iBufSize) noexcept +{ + return ConvertTagToStringInternal(iTag, result, iBufSize); +} + +/** + ConvertTagToString can be used with fixed buffers. + Use ConvertiTagTo[Sz|Wz]Tag for non-fixed buffers. + + wchar_t wzTag[MAX_TAG_CCH]; + ConvertTagToString(tag, wzTag); +*/ +template +inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ char (&szOut)[cch]) noexcept +{ + static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); + (void)ConvertiTagToSzTag(iTag, szOut, cch); +} + +template +inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ wchar_t (&wzOut)[cch]) noexcept +{ + static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); + (void)ConvertiTagToWzTag(iTag, wzOut, cch); +} + +template +inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ char16_t (&wzOut)[cch]) noexcept +{ + static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); + (void)ConvertTagToStringInternal(iTag, wzOut, cch); +} + +template +inline void ConvertTagToString(uint32_t iTag, _Out_ _Post_z_ char32_t (&wzOut)[cch]) noexcept +{ + static_assert(cch >= MAX_TAG_CCH, "buffer is too small"); + (void)ConvertTagToStringInternal(iTag, wzOut, cch); +} + +/** + Converts character buffer to integer tag +*/ +template +inline uint32_t ConvertStringToTagInternal(_In_count_(cch) const T* wz, size_t cch) noexcept +{ + if (4 == cch) + { + return static_cast((wz[0] << 24) | (wz[1] << 16) | (wz[2] << 8) | wz[3]); + } + + if (5 == cch) + { + return static_cast( + ((((((((details::TagLetterConvertValue(wz[0])) << 6) + details::TagLetterConvertValue(wz[1])) << 6) + + details::TagLetterConvertValue(wz[2])) + << 6) + + details::TagLetterConvertValue(wz[3])) + << 6) + + details::TagLetterConvertValue(wz[4])); + } + + return 0; +} + +inline uint32_t ConvertStringToTag(_In_count_(cch) const wchar_t* wz, size_t cch) noexcept +{ + return ConvertStringToTagInternal(wz, cch); +} + +inline uint32_t ConvertStringToTag(_In_count_(cch) const char* wz, size_t cch) noexcept +{ + return ConvertStringToTagInternal(wz, cch); +} + +inline uint32_t ConvertStringToTag(_In_count_(cch) const char16_t* wz, size_t cch) noexcept +{ + return ConvertStringToTagInternal(wz, cch); +} + +inline uint32_t ConvertStringToTag(_In_count_(cch) const char32_t* wz, size_t cch) noexcept +{ + return ConvertStringToTagInternal(wz, cch); +} + +/** + Converts character buffer to integer tag inferring the buffer size +*/ +template +inline uint32_t ConvertStringToTag(T (&wzOut)[cch]) noexcept +{ + static_assert(cch > 0, "No point in converting a zero sized buffer"); + static_assert(cch <= MAX_TAG_CCH, "No parsed buffer should be greater than MAX_TAG_CCH"); + // inferring the size assumes that the string in the buffer is null terminated so we + // ignore the last character since this is the equivalent of what strlen/wcslen do + return ConvertStringToTag(wzOut, cch - 1); +} + +/** + A RAII holder converting a tag value into a string +*/ +template +class TagHolder +{ +public: + /** + @param tag value + @param bool value indicating whether or not untagged values should result in an empty string + */ + TagHolder(uint32_t iTag, bool formatZero) noexcept + { + if (!formatZero && details::IsUntagged(iTag)) + return; + + ConvertTagToString(iTag, m_szTag); + } + + /** + @param tag value + */ + TagHolder(uint32_t iTag) noexcept : TagHolder(iTag, true) {} + + /** + @return a pointer to a null-terminated character buffer + @deprecated prefer c_str() instead + */ + _Ret_z_ T const* const GetPCWSTR() const noexcept + { + return this->c_str(); + } + + /** + @return a pointer to a null-terminated character buffer + */ + _Ret_z_ T const* const c_str() const noexcept + { + return m_szTag; + } + + /** + @return a pointer to a null-terminated character buffer + */ + _Ret_z_ operator T const * const() const noexcept + { + return this->c_str(); + } + +private: + T m_szTag[MAX_TAG_CCH] = {0}; +}; + +using WzTag = TagHolder; +using SzTag = TagHolder; +}; // namespace TaggingUtilities + #endif // __cplusplus #endif // LIBLET_TAGUTILS_TAGUTILS_H \ No newline at end of file diff --git a/libs/tagUtils/tests/paramCheckTest.cpp b/libs/tagUtils/tests/paramCheckTest.cpp index 9f06137..7e8bc0d 100644 --- a/libs/tagUtils/tests/paramCheckTest.cpp +++ b/libs/tagUtils/tests/paramCheckTest.cpp @@ -9,30 +9,31 @@ OACR_WARNING_DISABLE(CAST_CAN_BE_CONST, "The CppUnitTest framework runs afoul of OACR_WARNING_DISABLE(FUNC_COULD_BE_NOTHROW, "The CppUnitTest framework runs afoul of default OACR rules for liblets") OACR_WARNING_DISABLE(STATIC_FUNCTION, "The CppUnitTest framework runs afoul of default OACR rules for liblets") -TEST_CLASS(ParamChecking) +TEST_CLASS (ParamChecking) { - TEST_METHOD(NullBuffSz) - { - OACR_WARNING_SUPPRESS(INVALID_PARAM_VALUE_1, "Intentionally passing invalid parameter to test unexpected caller functionality."); - TestAssert::IsFalse(TaggingUtilities::ConvertiTagToSzTag(1, nullptr, 10)); - } + TEST_METHOD(NullBuffSz) + { + OACR_WARNING_SUPPRESS( + INVALID_PARAM_VALUE_1, "Intentionally passing invalid parameter to test unexpected caller functionality."); + TestAssert::IsFalse(TaggingUtilities::ConvertiTagToSzTag(1, nullptr, 10)); + } - TEST_METHOD(NullBuffWz) - { - OACR_WARNING_SUPPRESS(INVALID_PARAM_VALUE_1, "Intentionally passing invalid parameter to test unexpected caller functionality."); - TestAssert::IsFalse(TaggingUtilities::ConvertiTagToWzTag(1, nullptr, 10)); - } + TEST_METHOD(NullBuffWz) + { + OACR_WARNING_SUPPRESS( + INVALID_PARAM_VALUE_1, "Intentionally passing invalid parameter to test unexpected caller functionality."); + TestAssert::IsFalse(TaggingUtilities::ConvertiTagToWzTag(1, nullptr, 10)); + } - TEST_METHOD(BuffTooSmallSz) - { + TEST_METHOD(BuffTooSmallSz) + { + char szActual[MAX_TAG_CCH - 1] = {0}; + TestAssert::IsFalse(TaggingUtilities::ConvertiTagToSzTag(1, szActual, _countof(szActual))); + } - char szActual[MAX_TAG_CCH-1] = {0}; - TestAssert::IsFalse(TaggingUtilities::ConvertiTagToSzTag(1, szActual, _countof(szActual))); - } - - TEST_METHOD(BuffTooSmallWz) - { - wchar_t wzActual[MAX_TAG_CCH-1] = {0}; - TestAssert::IsFalse(TaggingUtilities::ConvertiTagToWzTag(1, wzActual, _countof(wzActual))); - } + TEST_METHOD(BuffTooSmallWz) + { + wchar_t wzActual[MAX_TAG_CCH - 1] = {0}; + TestAssert::IsFalse(TaggingUtilities::ConvertiTagToWzTag(1, wzActual, _countof(wzActual))); + } }; diff --git a/libs/tagUtils/tests/reserve.cpp b/libs/tagUtils/tests/reserve.cpp index c251119..5bb10d8 100644 --- a/libs/tagUtils/tests/reserve.cpp +++ b/libs/tagUtils/tests/reserve.cpp @@ -10,116 +10,115 @@ OACR_WARNING_DISABLE(FUNC_COULD_BE_NOEXCEPT, "The CppUnitTest framework runs afo OACR_WARNING_DISABLE(FUNC_COULD_BE_NOTHROW, "The CppUnitTest framework runs afoul of default OACR rules for liblets") OACR_WARNING_DISABLE(STATIC_FUNCTION, "The CppUnitTest framework runs afoul of default OACR rules for liblets") -TEST_CLASS(MsoReserveTagTests) +TEST_CLASS (MsoReserveTagTests) { - static void SyntaxTestsForTool() - { - MsoReserveTag a(0); // not tagged because the tagger doesn't know about ctor's on objects - MsoReserveTag b{0}; // same - auto c = MsoReserveTag(0x0201658c /* tag_cawwm */); // tagged because looks like c-style function call - auto d = MsoReserveTag{0}; // not tagged because tagger doesn't know anything about uniform initialization + static void SyntaxTestsForTool() + { + MsoReserveTag a(0); // not tagged because the tagger doesn't know about ctor's on objects + MsoReserveTag b{0}; // same + auto c = MsoReserveTag(0x0201658c /* tag_cawwm */); // tagged because looks like c-style function call + auto d = MsoReserveTag{0}; // not tagged because tagger doesn't know anything about uniform initialization - DoSomethingWithTag(MsoReserveTag(0x02015415 /* tag_cavqv */)); - DoSomethingWithTag(MsoReserveTag{0}); - } + DoSomethingWithTag(MsoReserveTag(0x02015415 /* tag_cavqv */)); + DoSomethingWithTag(MsoReserveTag{0}); + } - static void DoSomethingWithTag(MsoReserveTag) noexcept - { - } + static void DoSomethingWithTag(MsoReserveTag) noexcept {} - static void SyntaxTestsForToolWithVar(uint32_t value) noexcept - { - MsoReserveTag a(value); // not tagged because the tagger doesn't know about ctor's on objects - MsoReserveTag b{value}; // same - auto c = MsoReserveTag(value); // tagged because looks like c-style function call - auto d = MsoReserveTag{value}; // not tagged because tagger doesn't know anything about uniform initialization - - DoSomethingWithTag(MsoReserveTag(value)); - DoSomethingWithTag(MsoReserveTag{value}); - } + static void SyntaxTestsForToolWithVar(uint32_t value) noexcept + { + MsoReserveTag a(value); // not tagged because the tagger doesn't know about ctor's on objects + MsoReserveTag b{value}; // same + auto c = MsoReserveTag(value); // tagged because looks like c-style function call + auto d = MsoReserveTag{value}; // not tagged because tagger doesn't know anything about uniform initialization - // Standard AssertTag #define isn't available here because - // asserts rely on Tag's - static void AssertTag(bool, uint32_t) noexcept - {} + DoSomethingWithTag(MsoReserveTag(value)); + DoSomethingWithTag(MsoReserveTag{value}); + } - static void FailedSyntaxTestsForToolWithEmbeddedParens() noexcept - { - struct MyTagUnderlyingValueHoldingType { - uint32_t value {0}; - }; + // Standard AssertTag #define isn't available here because + // asserts rely on Tag's + static void AssertTag(bool, uint32_t) noexcept {} - MyTagUnderlyingValueHoldingType t; + static void FailedSyntaxTestsForToolWithEmbeddedParens() noexcept + { + struct MyTagUnderlyingValueHoldingType + { + uint32_t value{0}; + }; + MyTagUnderlyingValueHoldingType t; - // Intentionally ignoring as these do not parse due with the existing tagger regexes - // probably because they're more than just a simple variable to detect - // ASSERTTAG_IGNORE_START - DoSomethingWithTag(MsoReserveTag(t.value)); - DoSomethingWithTag(MsoReserveTag{t.value}); + // Intentionally ignoring as these do not parse due with the existing tagger regexes + // probably because they're more than just a simple variable to detect + // ASSERTTAG_IGNORE_START + DoSomethingWithTag(MsoReserveTag(t.value)); + DoSomethingWithTag(MsoReserveTag{t.value}); - DoSomethingWithTag(MsoReserveTag(MyTagUnderlyingValueHoldingType().value)); - DoSomethingWithTag(MsoReserveTag{MyTagUnderlyingValueHoldingType().value}); + DoSomethingWithTag(MsoReserveTag(MyTagUnderlyingValueHoldingType().value)); + DoSomethingWithTag(MsoReserveTag{MyTagUnderlyingValueHoldingType().value}); - // This is an example using AssertTag to demonstrate the replacement issue - // doesn't exist exist with MsoReserveTag - AssertTag(true, t.value); - AssertTag(true, MyTagUnderlyingValueHoldingType().value); - // ASSERTTAG_IGNORE_FINISH - } + // This is an example using AssertTag to demonstrate the replacement issue + // doesn't exist exist with MsoReserveTag + AssertTag(true, t.value); + AssertTag(true, MyTagUnderlyingValueHoldingType().value); + // ASSERTTAG_IGNORE_FINISH + } - TEST_METHOD(ObjHasStrongType) - { - auto value = MsoReserveTag(0x0201658d /* tag_cawwn */); - auto expected = UNTAGGED; + TEST_METHOD(ObjHasStrongType) + { + auto value = MsoReserveTag(0x0201658d /* tag_cawwn */); + auto expected = UNTAGGED; - bool isSameType = std::is_same::value; - TestAssert::IsFalse(isSameType); + bool isSameType = std::is_same::value; + TestAssert::IsFalse(isSameType); - // Intentionally unreferenced params - value;expected; - } + // Intentionally unreferenced params + value; + expected; + } - TEST_METHOD(UntaggedReserve) - { -// Intentionally ignoring to prove that MsoReserve is pinned to the UNTAGGED value -// ASSERTTAG_IGNORE_START - auto value = MsoReserve(); -// ASSERTTAG_IGNORE_FINISH - auto expected = UNTAGGED; + TEST_METHOD(UntaggedReserve) + { + // Intentionally ignoring to prove that MsoReserve is pinned to the UNTAGGED value + // ASSERTTAG_IGNORE_START + auto value = MsoReserve(); + // ASSERTTAG_IGNORE_FINISH + auto expected = UNTAGGED; - TestAssert::IsTrue(value == expected); - } + TestAssert::IsTrue(value == expected); + } - TEST_METHOD(TaggedReserve) - { - const uint32_t expected = 0x001c0797; - auto value = MsoReserveTag(expected); + TEST_METHOD(TaggedReserve) + { + const uint32_t expected = 0x001c0797; + auto value = MsoReserveTag(expected); - TestAssert::IsTrue(value == expected); - } + TestAssert::IsTrue(value == expected); + } - TEST_METHOD(TagEnumAssignment) - { - const uint32_t expected = 10; -// Intentionally ignoring to prove assignment to a specific value -// ASSERTTAG_IGNORE_START - enum class MyEnum : uint32_t { - value = MsoReserveTag(10) - }; -// ASSERTTAG_IGNORE_FINISH - static_assert(expected == static_cast(MyEnum::value), "verify constexpr assignment"); - TestAssert::IsTrue(true, L"Compilation is success"); - } + TEST_METHOD(TagEnumAssignment) + { + const uint32_t expected = 10; + // Intentionally ignoring to prove assignment to a specific value + // ASSERTTAG_IGNORE_START + enum class MyEnum : uint32_t + { + value = MsoReserveTag(10) + }; + // ASSERTTAG_IGNORE_FINISH + static_assert(expected == static_cast(MyEnum::value), "verify constexpr assignment"); + TestAssert::IsTrue(true, L"Compilation is success"); + } - TEST_METHOD(TagConstAssignment) - { - const uint32_t expected = 10; -// Intentionally ignoring to prove assignment to a specific value -// ASSERTTAG_IGNORE_START - static const uint32_t value = MsoReserveTag(10); -// ASSERTTAG_IGNORE_FINISH - static_assert(expected == value, "verify constexpr assignment"); - TestAssert::IsTrue(true, L"Compilation is success"); - } + TEST_METHOD(TagConstAssignment) + { + const uint32_t expected = 10; + // Intentionally ignoring to prove assignment to a specific value + // ASSERTTAG_IGNORE_START + static const uint32_t value = MsoReserveTag(10); + // ASSERTTAG_IGNORE_FINISH + static_assert(expected == value, "verify constexpr assignment"); + TestAssert::IsTrue(true, L"Compilation is success"); + } }; diff --git a/libs/tagUtils/tests/tagHolderTest.cpp b/libs/tagUtils/tests/tagHolderTest.cpp index 9e90a8d..9e14481 100644 --- a/libs/tagUtils/tests/tagHolderTest.cpp +++ b/libs/tagUtils/tests/tagHolderTest.cpp @@ -9,58 +9,57 @@ OACR_WARNING_DISABLE(CAST_CAN_BE_CONST, "The CppUnitTest framework runs afoul of OACR_WARNING_DISABLE(FUNC_COULD_BE_NOTHROW, "The CppUnitTest framework runs afoul of default OACR rules for liblets") OACR_WARNING_DISABLE(STATIC_FUNCTION, "The CppUnitTest framework runs afoul of default OACR rules for liblets") -TEST_CLASS(TagHolderTesting) +TEST_CLASS (TagHolderTesting) { - TEST_METHOD(CharType) - { - TaggingUtilities::SzTag tag(0); - TestAssert::AreEqual("00000", tag.GetPCWSTR()); - } + TEST_METHOD(CharType) + { + TaggingUtilities::SzTag tag(0); + TestAssert::AreEqual("00000", tag.GetPCWSTR()); + } - TEST_METHOD(CharType_ImplicitCast) - { - TaggingUtilities::SzTag tag(0); - TestAssert::AreEqual("00000", tag); - } + TEST_METHOD(CharType_ImplicitCast) + { + TaggingUtilities::SzTag tag(0); + TestAssert::AreEqual("00000", tag); + } - TEST_METHOD(CharType_ZeroIsEmpty) - { - TaggingUtilities::SzTag tag(0, false); - TestAssert::AreEqual("", tag); - } + TEST_METHOD(CharType_ZeroIsEmpty) + { + TaggingUtilities::SzTag tag(0, false); + TestAssert::AreEqual("", tag); + } - TEST_METHOD(CharType_UntaggedIsEmpty) - { - TaggingUtilities::SzTag tag(UNTAGGED, false /* formatZero */); - TestAssert::AreEqual("", tag); - } + TEST_METHOD(CharType_UntaggedIsEmpty) + { + TaggingUtilities::SzTag tag(UNTAGGED, false /* formatZero */); + TestAssert::AreEqual("", tag); + } - TEST_METHOD(CharType_NoValueIsEmpty) - { - const uint32_t c_dwFiveTag = 0x001c0797; - OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); - const char c_szFiveTag[] = "aha4x"; - - TaggingUtilities::SzTag tag(c_dwFiveTag, false /* formatZero */); - TestAssert::AreEqual(c_szFiveTag, tag); - } + TEST_METHOD(CharType_NoValueIsEmpty) + { + const uint32_t c_dwFiveTag = 0x001c0797; + OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); + const char c_szFiveTag[] = "aha4x"; + TaggingUtilities::SzTag tag(c_dwFiveTag, false /* formatZero */); + TestAssert::AreEqual(c_szFiveTag, tag); + } - TEST_METHOD(WCharType) - { - TaggingUtilities::WzTag tag(0); - TestAssert::AreEqual(L"00000", tag.GetPCWSTR()); - } + TEST_METHOD(WCharType) + { + TaggingUtilities::WzTag tag(0); + TestAssert::AreEqual(L"00000", tag.GetPCWSTR()); + } - TEST_METHOD(WCharType_ImplicitCast) - { - TaggingUtilities::WzTag tag(0); - TestAssert::AreEqual(L"00000", tag); - } + TEST_METHOD(WCharType_ImplicitCast) + { + TaggingUtilities::WzTag tag(0); + TestAssert::AreEqual(L"00000", tag); + } - TEST_METHOD(WCharType_ZeroIsEmpty) - { - TaggingUtilities::WzTag tag(0, false /* formatZero */); - TestAssert::AreEqual(L"", tag); - } + TEST_METHOD(WCharType_ZeroIsEmpty) + { + TaggingUtilities::WzTag tag(0, false /* formatZero */); + TestAssert::AreEqual(L"", tag); + } }; diff --git a/libs/tagUtils/tests/toStringTest.cpp b/libs/tagUtils/tests/toStringTest.cpp index 7cac703..ea05eda 100644 --- a/libs/tagUtils/tests/toStringTest.cpp +++ b/libs/tagUtils/tests/toStringTest.cpp @@ -12,108 +12,108 @@ OACR_WARNING_DISABLE(FUNC_COULD_BE_NOEXCEPT, "The CppUnitTest framework runs afo OACR_WARNING_DISABLE(FUNC_COULD_BE_NOTHROW, "The CppUnitTest framework runs afoul of default OACR rules for liblets") OACR_WARNING_DISABLE(STATIC_FUNCTION, "The CppUnitTest framework runs afoul of default OACR rules for liblets") -template +template static void TestSuccessfulConvertToString(uint32_t iTag, const T* szExpected) noexcept { - T szActual[MAX_TAG_CCH] = { 0 }; - TaggingUtilities::ConvertTagToString(iTag, szActual); - TestAssert::AreEqual(szExpected, szActual); + T szActual[MAX_TAG_CCH] = {0}; + TaggingUtilities::ConvertTagToString(iTag, szActual); + TestAssert::AreEqual(szExpected, szActual); } -TEST_CLASS(CriticalTagToString) +TEST_CLASS (CriticalTagToString) { - TEST_METHOD(MaxCriticalToString) - { - const uint32_t value = 65535; - const char* string = "65535"; - TestSuccessfulConvertToString(value, string); - } + TEST_METHOD(MaxCriticalToString) + { + const uint32_t value = 65535; + const char* string = "65535"; + TestSuccessfulConvertToString(value, string); + } - TEST_METHOD(MinCriticalToString) - { - const uint32_t value = 1; - const char* string = "1"; - TestSuccessfulConvertToString(value, string); - } + TEST_METHOD(MinCriticalToString) + { + const uint32_t value = 1; + const char* string = "1"; + TestSuccessfulConvertToString(value, string); + } - TEST_METHOD(TensPlaceString) - { - const uint32_t value = 25; - const char* string = "25"; - TestSuccessfulConvertToString(value, string); - } + TEST_METHOD(TensPlaceString) + { + const uint32_t value = 25; + const char* string = "25"; + TestSuccessfulConvertToString(value, string); + } - TEST_METHOD(HundredsPlaceString) - { - const uint32_t value = 512; - const char* string = "512"; - TestSuccessfulConvertToString(value, string); - } + TEST_METHOD(HundredsPlaceString) + { + const uint32_t value = 512; + const char* string = "512"; + TestSuccessfulConvertToString(value, string); + } - TEST_METHOD(ThousandsPlaceString) - { - const uint32_t value = 4192; - const char* string = "4192"; - TestSuccessfulConvertToString(value, string); - } + TEST_METHOD(ThousandsPlaceString) + { + const uint32_t value = 4192; + const char* string = "4192"; + TestSuccessfulConvertToString(value, string); + } - TEST_METHOD(CriticalTagToStringBufferTermination) - { - char szActual[] = "abcdfeghi"; - const char* szExpected = "5192"; - TaggingUtilities::ConvertTagToString(5192, szActual); - TestAssert::AreEqual(szExpected, szActual); - } - - TEST_METHOD(TheWzVersionWorksToo) - { - const uint32_t c_dwCritTag = 13000; - const wchar_t* c_wzCritTag = L"13000"; - TestSuccessfulConvertToString(c_dwCritTag, c_wzCritTag); - } + TEST_METHOD(CriticalTagToStringBufferTermination) + { + char szActual[] = "abcdfeghi"; + const char* szExpected = "5192"; + TaggingUtilities::ConvertTagToString(5192, szActual); + TestAssert::AreEqual(szExpected, szActual); + } + + TEST_METHOD(TheWzVersionWorksToo) + { + const uint32_t c_dwCritTag = 13000; + const wchar_t* c_wzCritTag = L"13000"; + TestSuccessfulConvertToString(c_dwCritTag, c_wzCritTag); + } }; static const uint32_t c_dwFourTag = 2038004346; static const char c_szFourTag[] = "yyzz"; static const wchar_t c_wzFourTag[] = L"yyzz"; -TEST_CLASS(FourCharacterToString) +TEST_CLASS (FourCharacterToString) { - TEST_METHOD(SuccessSz) - { - TestSuccessfulConvertToString(c_dwFourTag, c_szFourTag); - } + TEST_METHOD(SuccessSz) + { + TestSuccessfulConvertToString(c_dwFourTag, c_szFourTag); + } - TEST_METHOD(SuccessWz) - { - TestSuccessfulConvertToString(c_dwFourTag, c_wzFourTag); - } + TEST_METHOD(SuccessWz) + { + TestSuccessfulConvertToString(c_dwFourTag, c_wzFourTag); + } }; // TESTCLASS static const uint32_t c_dwFiveTag = 0x001c0797; static const char c_szFiveTag[] = "aha4x"; static const wchar_t c_wzFiveTag[] = L"aha4x"; -TEST_CLASS(FiveCharacterToString) +TEST_CLASS (FiveCharacterToString) { - // 0 is a special case tag since we always pad it out to five characters - TEST_METHOD(TagZeroSz) - { - TestSuccessfulConvertToString(0, "00000"); - } + // 0 is a special case tag since we always pad it out to five characters + TEST_METHOD(TagZeroSz) + { + TestSuccessfulConvertToString(0, "00000"); + } - TEST_METHOD(TagZeroWz) - { - TestSuccessfulConvertToString(0, L"00000"); - } + TEST_METHOD(TagZeroWz) + { + TestSuccessfulConvertToString(0, L"00000"); + } - TEST_METHOD(SuccessSz) - { - TestSuccessfulConvertToString(c_dwFiveTag, c_szFiveTag); - } + TEST_METHOD(SuccessSz) + { + TestSuccessfulConvertToString(c_dwFiveTag, c_szFiveTag); + } - TEST_METHOD(SuccessWz) - { - TestSuccessfulConvertToString(c_dwFiveTag, c_wzFiveTag); - } + TEST_METHOD(SuccessWz) + { + TestSuccessfulConvertToString(c_dwFiveTag, c_wzFiveTag); + } // Motif doesn't yet implement u16 and u32 C++ character types/strings to UnitTestString #if 0 @@ -130,12 +130,12 @@ TEST_CLASS(FiveCharacterToString) } #endif - TEST_METHOD(UnexpectedCharacter) - { - const wchar_t* wzInvalidTag = L"ab&cd"; // '&' is not in the allowed namespace a-z0-9 - const wchar_t* wzExpectedConversion = L"ab*cd"; - uint32_t tag = TaggingUtilities::ConvertStringToTag(wzInvalidTag, wcslen(wzInvalidTag)); + TEST_METHOD(UnexpectedCharacter) + { + const wchar_t* wzInvalidTag = L"ab&cd"; // '&' is not in the allowed namespace a-z0-9 + const wchar_t* wzExpectedConversion = L"ab*cd"; + uint32_t tag = TaggingUtilities::ConvertStringToTag(wzInvalidTag, wcslen(wzInvalidTag)); - TestSuccessfulConvertToString(tag, wzExpectedConversion); - } + TestSuccessfulConvertToString(tag, wzExpectedConversion); + } }; // TESTCLASS diff --git a/libs/tagUtils/tests/toTagTest.cpp b/libs/tagUtils/tests/toTagTest.cpp index 24f6925..5959a26 100644 --- a/libs/tagUtils/tests/toTagTest.cpp +++ b/libs/tagUtils/tests/toTagTest.cpp @@ -10,100 +10,99 @@ OACR_WARNING_DISABLE(FUNC_COULD_BE_NOTHROW, "The CppUnitTest framework runs afou OACR_WARNING_DISABLE(STATIC_FUNCTION, "The CppUnitTest framework runs afoul of default OACR rules for liblets") // ConvertStringToTag has a "bug" in it where it doesn't handle critical tags. This is just to pin behavior -TEST_CLASS(CriticalCharacterToTag) +TEST_CLASS (CriticalCharacterToTag) { - TEST_METHOD(ToTagThreeChar) - { - const wchar_t* wzCritTag = L"123"; - const uint32_t expected = 0; - uint32_t tag = TaggingUtilities::ConvertStringToTag(wzCritTag, wcslen(wzCritTag)); - TestAssert::AreEqual(expected, tag); // should expect 123 - } + TEST_METHOD(ToTagThreeChar) + { + const wchar_t* wzCritTag = L"123"; + const uint32_t expected = 0; + uint32_t tag = TaggingUtilities::ConvertStringToTag(wzCritTag, wcslen(wzCritTag)); + TestAssert::AreEqual(expected, tag); // should expect 123 + } - TEST_METHOD(ToTagFourChar) - { - const wchar_t* wzCritTag = L"1234"; - const uint32_t expected = 825373492; - uint32_t tag = TaggingUtilities::ConvertStringToTag(wzCritTag, wcslen(wzCritTag)); - TestAssert::AreEqual(expected, tag); // should expect 1234 - } + TEST_METHOD(ToTagFourChar) + { + const wchar_t* wzCritTag = L"1234"; + const uint32_t expected = 825373492; + uint32_t tag = TaggingUtilities::ConvertStringToTag(wzCritTag, wcslen(wzCritTag)); + TestAssert::AreEqual(expected, tag); // should expect 1234 + } - TEST_METHOD(ToTagFiveChar) - { - const wchar_t* wzCritTag = L"13000"; - const uint32_t expected = 460695194; - uint32_t tag = TaggingUtilities::ConvertStringToTag(wzCritTag, wcslen(wzCritTag)); - TestAssert::AreEqual(expected, tag); // should expect 13000 - } + TEST_METHOD(ToTagFiveChar) + { + const wchar_t* wzCritTag = L"13000"; + const uint32_t expected = 460695194; + uint32_t tag = TaggingUtilities::ConvertStringToTag(wzCritTag, wcslen(wzCritTag)); + TestAssert::AreEqual(expected, tag); // should expect 13000 + } }; const wchar_t c_wzFourTag[] = L"yyzz"; const char c_szFourTag[] = "yyzz"; const uint32_t c_dwFourTag = 2038004346; -TEST_CLASS(FourCharacterToTag) +TEST_CLASS (FourCharacterToTag) { - TEST_METHOD(ToTagWz) - { - uint32_t tag = TaggingUtilities::ConvertStringToTag(c_wzFourTag, wcslen(c_wzFourTag)); - TestAssert::AreEqual(tag, c_dwFourTag); - } + TEST_METHOD(ToTagWz) + { + uint32_t tag = TaggingUtilities::ConvertStringToTag(c_wzFourTag, wcslen(c_wzFourTag)); + TestAssert::AreEqual(tag, c_dwFourTag); + } - TEST_METHOD(ToTagSz) - { - uint32_t tag = TaggingUtilities::ConvertStringToTag(c_szFourTag, strlen(c_szFourTag)); - TestAssert::AreEqual(tag, c_dwFourTag); - } + TEST_METHOD(ToTagSz) + { + uint32_t tag = TaggingUtilities::ConvertStringToTag(c_szFourTag, strlen(c_szFourTag)); + TestAssert::AreEqual(tag, c_dwFourTag); + } }; const uint32_t c_dwFiveTag = 0x001c0797; const wchar_t c_wzFiveTag[] = L"aha4x"; const char c_szFiveTag[] = "aha4x"; -TEST_CLASS(FiveCharacterToTag) +TEST_CLASS (FiveCharacterToTag) { - TEST_METHOD(ToTagU16) - { - OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); - const char16_t sz[] = u"aha4x"; - uint32_t tag = TaggingUtilities::ConvertStringToTag(sz); - TestAssert::AreEqual(c_dwFiveTag, tag); - } + TEST_METHOD(ToTagU16) + { + OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); + const char16_t sz[] = u"aha4x"; + uint32_t tag = TaggingUtilities::ConvertStringToTag(sz); + TestAssert::AreEqual(c_dwFiveTag, tag); + } - TEST_METHOD(ToTagU32) - { - OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); - const char32_t sz[] = U"aha4x"; - uint32_t tag = TaggingUtilities::ConvertStringToTag(sz); - TestAssert::AreEqual(c_dwFiveTag, tag); - } + TEST_METHOD(ToTagU32) + { + OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); + const char32_t sz[] = U"aha4x"; + uint32_t tag = TaggingUtilities::ConvertStringToTag(sz); + TestAssert::AreEqual(c_dwFiveTag, tag); + } - TEST_METHOD(ToTagWz) - { - uint32_t tag = TaggingUtilities::ConvertStringToTag(c_wzFiveTag); - TestAssert::AreEqual(c_dwFiveTag, tag); - } + TEST_METHOD(ToTagWz) + { + uint32_t tag = TaggingUtilities::ConvertStringToTag(c_wzFiveTag); + TestAssert::AreEqual(c_dwFiveTag, tag); + } - TEST_METHOD(ToTagSz) - { - uint32_t tag = TaggingUtilities::ConvertStringToTag(c_szFiveTag); - TestAssert::AreEqual(c_dwFiveTag, tag); - } + TEST_METHOD(ToTagSz) + { + uint32_t tag = TaggingUtilities::ConvertStringToTag(c_szFiveTag); + TestAssert::AreEqual(c_dwFiveTag, tag); + } - TEST_METHOD(UnexpectedCharacterWz) - { - OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); - const wchar_t wzFiveTag[] = L"ab&cd"; - const uint32_t expected = 417923; - uint32_t tag = TaggingUtilities::ConvertStringToTag(wzFiveTag); - TestAssert::AreEqual(expected, tag); - } + TEST_METHOD(UnexpectedCharacterWz) + { + OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); + const wchar_t wzFiveTag[] = L"ab&cd"; + const uint32_t expected = 417923; + uint32_t tag = TaggingUtilities::ConvertStringToTag(wzFiveTag); + TestAssert::AreEqual(expected, tag); + } - - TEST_METHOD(UnexpectedCharacterSz) - { - OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); - const char szTag[] = "ab&cd"; - const uint32_t expected = 417923; - uint32_t tag = TaggingUtilities::ConvertStringToTag(szTag); - TestAssert::AreEqual(expected, tag); - } + TEST_METHOD(UnexpectedCharacterSz) + { + OACR_WARNING_SUPPRESS(LOCAL_ARRAY_SHOULD_BE_PTR, "test code needs array for template size deduction"); + const char szTag[] = "ab&cd"; + const uint32_t expected = 417923; + uint32_t tag = TaggingUtilities::ConvertStringToTag(szTag); + TestAssert::AreEqual(expected, tag); + } }; diff --git a/package.json b/package.json index dd25ad8..983111c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "license": "MIT", "devDependencies": { "beachball": "1.23.3", - "clang-format": "1.2.4", + "clang-format": "1.4.0", "husky": "^3.0.9" } } diff --git a/yarn.lock b/yarn.lock index cfc69c4..473e3fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -130,10 +130,10 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -clang-format@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.2.4.tgz#4bb4b0a98180428deb093cf20982e9fc1af20b6c" - integrity sha512-sw+nrGUp3hvmANd1qF8vZPuezSYQAiXgGBiEtkXTtJnnu6b00fCqkkDIsnRKrNgg4nv6NYZE92ejvOMIXZoejw== +clang-format@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.4.0.tgz#1ee2f10637eb5bb0bd7d0b82c949af68e848367e" + integrity sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA== dependencies: async "^1.5.2" glob "^7.0.0"