diff --git a/cpp/Platform.Disposables/DisposableBase.h b/cpp/Platform.Disposables/DisposableBase.h index 7a51e1b..54d17b4 100644 --- a/cpp/Platform.Disposables/DisposableBase.h +++ b/cpp/Platform.Disposables/DisposableBase.h @@ -1,14 +1,19 @@ -namespace Platform::Disposables +#pragma once +#include +#include +#include +#include + +namespace Platform::Disposables { class DisposableBase : public IDisposable { - private: static readonly ConcurrentStack> _disposablesWeekReferencesStack = ConcurrentStack>(); - private: volatile std::int32_t _disposed; + private: std::atomic _disposed; public: bool IsDisposed() { - return _disposed > 0; + return _disposed.load() > 0; } protected: virtual std::string ObjectName() @@ -26,12 +31,10 @@ return false; } - static DisposableBase() { std::atexit(OnProcessExit); } protected: DisposableBase() { _disposed = 0; - _disposablesWeekReferencesStack.Push(WeakReference(this, false)); } ~DisposableBase() { Destruct(); } @@ -41,14 +44,13 @@ public: void Dispose() { this->Dispose(true); - GC.SuppressFinalize(this); } public: void Destruct() { try { - if (!IsDisposed) + if (!IsDisposed()) { this->Dispose(false); } @@ -61,28 +63,17 @@ protected: virtual void Dispose(bool manual) { - auto originalDisposedValue = Interlocked.CompareExchange(ref _disposed, 1, 0); - auto wasDisposed = originalDisposedValue > 0; - if (wasDisposed && !AllowMultipleDisposeCalls && manual) + std::int32_t expected = 0; + auto wasDisposed = !_disposed.compare_exchange_strong(expected, 1); + 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); } } - private: static void OnProcessExit() - { - while (_disposablesWeekReferencesStack.TryPop(out WeakReference weakReference)) - { - if (weakReference.TryGetTarget(out DisposableBase disposable)) - { - GC.SuppressFinalize(disposable); - disposable.Destruct(); - } - } - } }; } diff --git a/experiments/test_compilation b/experiments/test_compilation new file mode 100755 index 0000000..f8e193f Binary files /dev/null and b/experiments/test_compilation differ diff --git a/experiments/test_compilation.cpp b/experiments/test_compilation.cpp new file mode 100644 index 0000000..dda42bb --- /dev/null +++ b/experiments/test_compilation.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +// Mock System::IDisposable +namespace System +{ + class IDisposable + { + public: + virtual void Dispose() = 0; + }; +} + +// Mock Platform::Disposables::IDisposable +namespace Platform::Disposables +{ + class IDisposable : public System::IDisposable + { + public: + virtual bool IsDisposed() = 0; + virtual void Destruct() = 0; + }; +} + +// Mock Platform::Exceptions::ExceptionExtensions +namespace Platform::Exceptions +{ + class ExceptionExtensions + { + public: + static void Ignore(const std::exception& exception) + { + // Mock implementation + } + }; + + class Ensure + { + public: + static Ensure Always; + }; + + Ensure Ensure::Always; +} + +// Mock Platform::Disposables::EnsureExtensions +namespace Platform::Disposables +{ + class EnsureExtensions + { + public: + static void NotDisposed(Platform::Exceptions::Ensure& ensure, void* obj, const std::string& name, const std::string& message) + { + // Mock implementation - throw an exception + throw std::runtime_error(message); + } + }; +} + +// Include the actual DisposableBase +#include "../cpp/Platform.Disposables/DisposableBase.h" + +// Test implementation +class TestDisposable : public Platform::Disposables::DisposableBase +{ +protected: + void Dispose(bool manual, bool wasDisposed) override + { + std::cout << "TestDisposable::Dispose called with manual=" << manual << ", wasDisposed=" << wasDisposed << std::endl; + } +}; + +int main() +{ + TestDisposable test; + std::cout << "IsDisposed before: " << test.IsDisposed() << std::endl; + test.Platform::Disposables::DisposableBase::Dispose(); + std::cout << "IsDisposed after: " << test.IsDisposed() << std::endl; + return 0; +} \ No newline at end of file