diff --git a/cpp/Platform.Disposables/Disposable.h b/cpp/Platform.Disposables/Disposable.h index 7d0e907..e813850 100644 --- a/cpp/Platform.Disposables/Disposable.h +++ b/cpp/Platform.Disposables/Disposable.h @@ -1,4 +1,12 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_DISPOSABLE_H +#define DISPOSABLES_DISPOSABLE_H + +#include + +#include "DisposableBase.h" +#include "Disposal.h" + +namespace Platform::Disposables { template class Disposable; template<> class Disposable<> : public DisposableBase @@ -22,9 +30,6 @@ public: Disposable() { OnDispose = _emptyDelegate; } - public: Disposable(std::function action) : Disposable(action) { } - - public: Disposable(std::function disposal) : Disposable(disposal) { } protected: void Dispose(bool manual, bool wasDisposed) override { this->RaiseOnDisposeEvent(manual, wasDisposed); } @@ -32,7 +37,7 @@ public: template static bool TryDisposeAndResetToDefault(T* object) { - auto result = object.TryDispose(); + auto result = object->TryDispose(); if (result) { object = 0; @@ -40,4 +45,7 @@ return result; } }; -} \ No newline at end of file +} + + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/DisposableBase.h b/cpp/Platform.Disposables/DisposableBase.h index 9e651eb..7206191 100644 --- a/cpp/Platform.Disposables/DisposableBase.h +++ b/cpp/Platform.Disposables/DisposableBase.h @@ -1,12 +1,27 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_DISPOSABLE_BASE_H +#define DISPOSABLES_DISPOSABLE_BASE_H + +#include + + + + +#include "IDisposable.h" +#include "EnsureExtensions.h" +#include "../../../Exceptions/cpp/Platform.Exceptions/IgnoredExceptions.h" +#include "../../../Exceptions/cpp/Platform.Exceptions/ExceptionExtensions.h" +#include "../../../Exceptions/cpp/Platform.Exceptions/Ensure.h" + + +namespace Platform::Disposables { class DisposableBase : public IDisposable { - private: static readonly ConcurrentStack> _disposablesWeekReferencesStack = ConcurrentStack>(); + private: static std::stack> _disposablesWeekReferencesStack; - private: volatile std::int32_t _disposed; + private: volatile std::atomic _disposed; - public: bool IsDisposed() + public: bool IsDisposed() override { return _disposed > 0; } @@ -26,29 +41,34 @@ return false; } - static DisposableBase() { std::atexit(OnProcessExit); } - protected: DisposableBase() + public: DisposableBase() { + std::shared_ptr this_ptr = std::shared_ptr(this); + std::weak_ptr this_weak = std::weak_ptr(this_ptr); + + _disposed = 0; - _disposablesWeekReferencesStack.Push(WeakReference(this, false)); + _disposablesWeekReferencesStack.push(this_weak); + std::atexit(OnProcessExit); } - ~DisposableBase() { Destruct(); } + //TODO: завязывайте с вызовом всякой виртуальщины в конструкторе/деструкторе + //~DisposableBase() { Destruct(); } + + public: virtual void Dispose(bool manual, bool wasDisposed) = 0; - protected: virtual void Dispose(bool manual, bool wasDisposed) = 0; - public: void Dispose() + public: void Dispose() override { this->Dispose(true); - GC.SuppressFinalize(this); } - public: void Destruct() + public: void Destruct() override { try { - if (!IsDisposed) + if (!IsDisposed()) { this->Dispose(false); } @@ -59,15 +79,16 @@ } } - protected: virtual void Dispose(bool manual) + public: virtual void Dispose(bool manual) { - auto originalDisposedValue = Interlocked.CompareExchange(ref _disposed, 1, 0); + int compare_value = 1; + bool originalDisposedValue = _disposed.compare_exchange_weak(compare_value, 0); auto wasDisposed = originalDisposedValue > 0; - if (wasDisposed && !AllowMultipleDisposeCalls && manual) + if (wasDisposed && !AllowMultipleDisposeCalls() && manual) { - Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, this, ObjectName, "Multiple dispose calls are not allowed. Override AllowMultipleDisposeCalls property to modify behavior."); + Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, this, ObjectName(), "Multiple dispose calls are not allowed. Override AllowMultipleDisposeCalls property to modify behavior."); } - if (AllowMultipleDisposeAttempts || !wasDisposed) + if (AllowMultipleDisposeAttempts() || !wasDisposed) { this->Dispose(manual, wasDisposed); } @@ -75,14 +96,20 @@ private: static void OnProcessExit() { - while (_disposablesWeekReferencesStack.TryPop(out WeakReference weakReference)) + while (!_disposablesWeekReferencesStack.empty()) { - if (weakReference.TryGetTarget(out DisposableBase disposable)) + auto weakReference = _disposablesWeekReferencesStack.top(); + _disposablesWeekReferencesStack.pop(); + + if (auto disposable = weakReference.lock()) { - GC.SuppressFinalize(disposable); - disposable.Destruct(); + disposable->Destruct(); } } } }; -} \ No newline at end of file +} + +std::stack> Platform::Disposables::DisposableBase::_disposablesWeekReferencesStack = std::stack>(); + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].h b/cpp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].h index a8cb670..ab70099 100644 --- a/cpp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].h +++ b/cpp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].h @@ -1,9 +1,17 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_DISPOSABLE_T1_T2_H +#define DISPOSABLES_DISPOSABLE_T1_T2_H + +#include "Disposal.h" +#include "Disposable[T].h" + +namespace Platform::Disposables { - template class Disposable; + template class Disposable : public Disposable { public: const TAuxiliary AuxiliaryObject; + public: Platform::Delegates::MulticastDelegate OnDispose; + public: const TPrimary Object; public: Disposable(TPrimary object, TAuxiliary auxiliaryObject, std::function action) : Disposable(object) @@ -18,11 +26,11 @@ }; } - public: Disposable(TPrimary object, TAuxiliary auxiliaryObject, std::function action) : Disposable(object, action) { return AuxiliaryObject = auxiliaryObject; } + public: Disposable(TPrimary object, TAuxiliary auxiliaryObject, std::function action) : Disposable(object, action) { AuxiliaryObject = auxiliaryObject; } - public: Disposable(TPrimary object, TAuxiliary auxiliaryObject, Disposal disposal) : Disposable(object, disposal) { return AuxiliaryObject = auxiliaryObject; } + public: Disposable(TPrimary object, TAuxiliary auxiliaryObject, Disposal disposal) : Disposable(object, disposal) { AuxiliaryObject = auxiliaryObject; } - public: Disposable(TPrimary object, TAuxiliary auxiliaryObject) : Disposable(object) { return AuxiliaryObject = auxiliaryObject; } + public: Disposable(TPrimary object, TAuxiliary auxiliaryObject) : Disposable(object) { AuxiliaryObject = auxiliaryObject; } public: Disposable(TPrimary object) : Disposable(object) { } @@ -44,5 +52,9 @@ AuxiliaryObject.TryDispose(); Object.TryDispose(); } + + }; } + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/Disposable[T].h b/cpp/Platform.Disposables/Disposable[T].h index 246d557..db8430b 100644 --- a/cpp/Platform.Disposables/Disposable[T].h +++ b/cpp/Platform.Disposables/Disposable[T].h @@ -1,6 +1,14 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_DISPOSABLE_T_H +#define DISPOSABLES_DISPOSABLE_T_H + + +#include "Disposal.h" +#include "Disposable.h" + + +namespace Platform::Disposables { - template class Disposable; + template class Disposable : public Disposable<> { public: const T Object; @@ -17,9 +25,9 @@ }; } - public: Disposable(T object, std::function action) : Disposable<>(action) { return Object = object; } + public: Disposable(T object, std::function action) : Disposable<>(action) { Object = object; } - public: Disposable(T object, Disposal disposal) : Disposable<>(disposal) { return Object = object; } + public: Disposable(T object, Disposal disposal) : Disposable<>(disposal) { Object = object; } public: Disposable(T object) { Object = object; } @@ -33,8 +41,15 @@ protected: void Dispose(bool manual, bool wasDisposed) override { - base.Dispose(manual, wasDisposed); + // о нет так можно делать только в visual c++ + // __super::Dispose(manual, wasDisposed) + // ---------------------------------- + // base.Dispose(manual, wasDisposed); + + RaiseOnDisposeEvent(manual, wasDisposed); Object.TryDispose(); } }; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/Disposal.h b/cpp/Platform.Disposables/Disposal.h index c305842..62a8fc3 100644 --- a/cpp/Platform.Disposables/Disposal.h +++ b/cpp/Platform.Disposables/Disposal.h @@ -1,4 +1,9 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_DISPOSAl_H +#define DISPOSABLES_DISPOSAl_H + +namespace Platform::Disposables { using Disposal = void(bool, bool); } + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/EnsureExtensions.h b/cpp/Platform.Disposables/EnsureExtensions.h index 1126638..7f23f16 100644 --- a/cpp/Platform.Disposables/EnsureExtensions.h +++ b/cpp/Platform.Disposables/EnsureExtensions.h @@ -1,23 +1,29 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_ENSURE_EXTENSION_H +#define DISPOSABLES_ENSURE_EXTENSION_H + + +namespace Platform::Disposables { class EnsureExtensions { - public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureAlwaysExtensionRoot root, IDisposable &disposable, std::string objectName, std::string message) + public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureAlwaysExtensionRoot root, IDisposable* disposable, std::string objectName, std::string message) { - if (disposable.IsDisposed) + if (disposable->IsDisposed()) { throw std::runtime_error(std::string("Attempt to access disposed object [").append(objectName).append("]: ").append(message).append(1, '.')); } } - public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureAlwaysExtensionRoot root, IDisposable &disposable, std::string objectName) { NotDisposed(root, disposable, objectName, {}); } + public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureAlwaysExtensionRoot root, IDisposable* disposable, std::string objectName) { NotDisposed(root, disposable, objectName, {}); } - public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureAlwaysExtensionRoot root, IDisposable &disposable) { NotDisposed(root, disposable, {}, {}); } + public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureAlwaysExtensionRoot root, IDisposable* disposable) { NotDisposed(root, disposable, {}, {}); } - public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureOnDebugExtensionRoot root, IDisposable &disposable, std::string objectName, std::string message) { Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, disposable, objectName, message); } + public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureOnDebugExtensionRoot root, IDisposable* disposable, std::string objectName, std::string message) { Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, disposable, objectName, message); } - public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureOnDebugExtensionRoot root, IDisposable &disposable, std::string objectName) { Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, disposable, objectName, {}); } + public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureOnDebugExtensionRoot root, IDisposable* disposable, std::string objectName) { Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, disposable, objectName, {}); } - public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureOnDebugExtensionRoot root, IDisposable &disposable) { Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, disposable, {}, {}); } + public: static void NotDisposed(Platform::Exceptions::ExtensionRoots::EnsureOnDebugExtensionRoot root, IDisposable* disposable) { Platform::Disposables::EnsureExtensions::NotDisposed(Platform::Exceptions::Ensure::Always, disposable, {}, {}); } }; } + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/GenericObjectExtensions.h b/cpp/Platform.Disposables/GenericObjectExtensions.h index cfb7680..1b6215a 100644 --- a/cpp/Platform.Disposables/GenericObjectExtensions.h +++ b/cpp/Platform.Disposables/GenericObjectExtensions.h @@ -1,4 +1,7 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_GENERIC_DISPOSABLE_H +#define DISPOSABLES_GENERIC_DISPOSABLE_H + +namespace Platform::Disposables { class GenericObjectExtensions { @@ -6,13 +9,17 @@ { try { - if (object is DisposableBase disposableBase) + if (std::is_base_of::value) // до изменения задания: if(disposableBase = (DisposableBase*)object) { - disposableBase.DisposeIfNotDisposed(); + auto disposableBase = (DisposableBase*)object; + + //TODO: add this method + //disposableBase->DisposeIfNotDisposed(); } - else if (object is System::IDisposable &disposable) + else if (std::is_base_of::value) // до изменения задания: if(disposable = (IDisposable*)object) { - disposable.Dispose(); + auto disposable = (IDisposable*)object; + disposable->Dispose(); } return true; } @@ -26,3 +33,5 @@ public: template static void DisposeIfPossible(T object) { TryDispose(object); } }; } + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/IDisposable.h b/cpp/Platform.Disposables/IDisposable.h index 5f4315e..534697b 100644 --- a/cpp/Platform.Disposables/IDisposable.h +++ b/cpp/Platform.Disposables/IDisposable.h @@ -1,4 +1,10 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_IDISPOSABLE_H +#define DISPOSABLES_IDISPOSABLE_H + +#include "System.IDisposable.h" + + +namespace Platform::Disposables { class IDisposable : public System::IDisposable { @@ -7,4 +13,6 @@ virtual void Destruct() = 0; }; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/IDisposableExtensions.h b/cpp/Platform.Disposables/IDisposableExtensions.h index 98c50cf..f5ae656 100644 --- a/cpp/Platform.Disposables/IDisposableExtensions.h +++ b/cpp/Platform.Disposables/IDisposableExtensions.h @@ -1,13 +1,20 @@ -namespace Platform::Disposables +#ifndef DISPOSABLES_IDISPOSABLE_EXTENSIONS_H +#define DISPOSABLES_IDISPOSABLE_EXTENSIONS_H + + + +namespace Platform::Disposables { class IDisposableExtensions { public: static void DisposeIfNotDisposed(IDisposable &disposable) { - if (!disposable.IsDisposed) + if (!disposable.IsDisposed()) { disposable.Dispose(); } } }; } + +#endif \ No newline at end of file diff --git a/cpp/Platform.Disposables/Platform.Disposables.h b/cpp/Platform.Disposables/Platform.Disposables.h index 2d77860..b18d696 100644 --- a/cpp/Platform.Disposables/Platform.Disposables.h +++ b/cpp/Platform.Disposables/Platform.Disposables.h @@ -3,11 +3,9 @@ #ifndef PLATFORM_DISPOSABLES #define PLATFORM_DISPOSABLES -//#include -//#include -#include -#include + + #include "System.IDisposable.h"