diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-07-18 15:44:29 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-18 15:44:29 -0400 |
| commit | 2e4b5770fa7e6dbf56845382706b33a22d6a025b (patch) | |
| tree | e58bcb7c446fcbffc8e1dd725636dbd737d946fc | |
| parent | da8f050f9865635e5778589e1e3883b614d73266 (diff) | |
Atomic ref counting for ISlangSharedLibrary (#2332)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Make ISlangSharedLibrary atomic ref counted.
Update docs to say most COM interfaces are *not* atomic ref counted.
* Upgrade slang-llvm to use version that atomic ref counts ISlangSharedLibrary.
* Fix some typos in docs.
* Fix ref count typo.
* Fix missing 'override'
| -rw-r--r-- | deps/target-deps.json | 10 | ||||
| -rw-r--r-- | docs/api-users-guide.md | 2 | ||||
| -rw-r--r-- | source/compiler-core/slang-downstream-compiler.cpp | 13 | ||||
| -rw-r--r-- | source/core/slang-com-object.h | 68 | ||||
| -rw-r--r-- | source/core/slang-shared-library.cpp | 5 | ||||
| -rw-r--r-- | source/core/slang-shared-library.h | 12 |
6 files changed, 93 insertions, 17 deletions
diff --git a/deps/target-deps.json b/deps/target-deps.json index 8266898b2..861f18289 100644 --- a/deps/target-deps.json +++ b/deps/target-deps.json @@ -4,14 +4,14 @@ "dependencies" : [ { "name" : "slang-llvm", - "baseUrl" : "https://github.com/shader-slang/slang-llvm/releases/download/v13.x-28/", + "baseUrl" : "https://github.com/shader-slang/slang-llvm/releases/download/v13.x-29/", "optional" : true, "packages" : { - "windows-x86_64" : { "type" : "url", "path" : "slang-llvm-13.x-28-win64.zip" }, - "windows-x86" : { "type": "url", "path" : "slang-llvm-13.x-28-win32.zip" }, - "linux-x86_64" : { "type": "url", "path" : "slang-llvm-v13.x-28-linux-x86_64-release.zip" }, - "macosx-x86_64" : { "type": "url", "path" : "slang-llvm-v13.x-28-macosx-x86_64-release.zip" } + "windows-x86_64" : { "type" : "url", "path" : "slang-llvm-13.x-29-win64.zip" }, + "windows-x86" : { "type": "url", "path" : "slang-llvm-13.x-29-win32.zip" }, + "linux-x86_64" : { "type": "url", "path" : "slang-llvm-v13.x-29-linux-x86_64-release.zip" }, + "macosx-x86_64" : { "type": "url", "path" : "slang-llvm-v13.x-29-macosx-x86_64-release.zip" } } }, { diff --git a/docs/api-users-guide.md b/docs/api-users-guide.md index 90e7be9bc..d8ab31bc4 100644 --- a/docs/api-users-guide.md +++ b/docs/api-users-guide.md @@ -459,6 +459,8 @@ This assumes Slang has been built with the C++ multithreaded runtime, as is the All other functions and methods are not [reentrant](https://en.wikipedia.org/wiki/Reentrancy_(computing)) and can only execute on a single thread. More precisely function and methods can only be called on a *single* thread at *any one time*. This means for example a global session can be used across multiple threads, as long as some synchronisation enforces that only one thread can be in a Slang call at any one time. +Much of the Slang API is available through [COM interfaces](https://en.wikipedia.org/wiki/Component_Object_Model). In strict COM interfaces should be atomically reference counted. Currently *MOST* Slang API COM interfaces are *NOT* atomic reference counted. One exception is the `ISlangSharedLibrary` interface when produced from [host-callable](cpu-target.md#host-callable). It is atomically reference counted, allowing it to persist and be used beyond the original compilation and be freed on a different thread. + A Slang compile request/s (`slang::ICompileRequest` or `SlangCompileRequest`) can be thought of belonging to the Slang global session (`slang::IGlobalSession` or `SlangSession`) it was created from. Note that *creating* a global session is currently a fairly costly process, whereas the cost of creating and destroying a request is relatively small. The *simplest* way to multithread would be for a thread to diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index 85726557e..2e30c23bc 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -360,11 +360,16 @@ SlangResult CommandLineDownstreamCompileResult::getHostCallableSharedLibrary(Com { return SLANG_FAIL; } - // The shared library needs to keep temp files in scope - RefPtr<TemporarySharedLibrary> sharedLib(new TemporarySharedLibrary(handle, m_moduleFilePath)); - sharedLib->m_temporaryFileSet = m_temporaryFiles; + + { + // The shared library needs to keep temp files in scope + auto temporarySharedLibrary = new TemporarySharedLibrary(handle, m_moduleFilePath); + // Make sure it gets a ref count + m_hostCallableSharedLibrary = temporarySharedLibrary; + // Set any additional info on the non COM pointer + temporarySharedLibrary->m_temporaryFileSet = m_temporaryFiles; + } - m_hostCallableSharedLibrary = sharedLib; outLibrary = m_hostCallableSharedLibrary; return SLANG_OK; } diff --git a/source/core/slang-com-object.h b/source/core/slang-com-object.h index 50dac5ba2..617b7ccca 100644 --- a/source/core/slang-com-object.h +++ b/source/core/slang-com-object.h @@ -6,6 +6,74 @@ namespace Slang { + +/// A base class for COM interfaces that require atomic ref counting +/// and are *NOT* derived from RefObject +class ComBaseObject +{ +public: + + /// If assigned the the ref count is *NOT* copied + ComBaseObject& operator=(const ComBaseObject&) { return *this; } + + /// Copy Ctor, does not copy ref count + ComBaseObject(const ComBaseObject&) : + m_refCount(0) + {} + + /// Default Ctor sets with no refs + ComBaseObject() + : m_refCount(0) + {} + + /// Dtor needs to be virtual to avoid needing to + /// Implement release for all derived types. + virtual ~ComBaseObject() + {} + +protected: + inline uint32_t _releaseImpl(); + + std::atomic<uint32_t> m_refCount; +}; + +// ------------------------------------------------------------------ +inline uint32_t ComBaseObject::_releaseImpl() +{ + // Check there is a ref count to avoid underflow + SLANG_ASSERT(m_refCount != 0); + const uint32_t count = --m_refCount; + if (count == 0) + { + delete this; + } + return count; +} + +#define SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE \ + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) \ + SLANG_OVERRIDE \ + { \ + void* intf = getInterface(uuid); \ + if (intf) \ + { \ + ++m_refCount; \ + *outObject = intf; \ + return SLANG_OK; \ + } \ + return SLANG_E_NO_INTERFACE; \ + } +#define SLANG_COM_BASE_IUNKNOWN_ADD_REF \ + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return ++m_refCount; } +#define SLANG_COM_BASE_IUNKNOWN_RELEASE \ + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return _releaseImpl(); } +#define SLANG_COM_BASE_IUNKNOWN_ALL \ + SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE \ + SLANG_COM_BASE_IUNKNOWN_ADD_REF \ + SLANG_COM_BASE_IUNKNOWN_RELEASE + + +/// COM object that derives from RefObject class ComObject : public RefObject { protected: diff --git a/source/core/slang-shared-library.cpp b/source/core/slang-shared-library.cpp index 1513b420f..f31c7d689 100644 --- a/source/core/slang-shared-library.cpp +++ b/source/core/slang-shared-library.cpp @@ -78,6 +78,8 @@ TemporarySharedLibrary::~TemporarySharedLibrary() SLANG_NO_THROW SlangResult SLANG_MCALL DefaultSharedLibrary::queryInterface(SlangUUID const& uuid, void** outObject) { + // Mechanism to cast to underlying type. + // NOTE! Purposefully does not ref count if (uuid == DefaultSharedLibrary::getTypeGuid()) { *outObject = this; @@ -86,7 +88,7 @@ SLANG_NO_THROW SlangResult SLANG_MCALL DefaultSharedLibrary::queryInterface(Slan if (uuid == ISlangUnknown::getTypeGuid() || uuid == ISlangSharedLibrary::getTypeGuid()) { - addReference(); + ++m_refCount; *outObject = static_cast<ISlangSharedLibrary*>(this); return SLANG_OK; } @@ -106,7 +108,6 @@ void* DefaultSharedLibrary::findSymbolAddressByName(char const* name) return SharedLibrary::findSymbolAddressByName(m_sharedLibraryHandle, name); } - String SharedLibraryUtils::getSharedLibraryFileName(void* symbolInLib) { #if defined(_WIN32) diff --git a/source/core/slang-shared-library.h b/source/core/slang-shared-library.h index 452379d68..44adb1ac6 100644 --- a/source/core/slang-shared-library.h +++ b/source/core/slang-shared-library.h @@ -5,6 +5,7 @@ #include "../../slang-com-helper.h" #include "../../slang-com-ptr.h" +#include "../core/slang-com-object.h" #include "../core/slang-io.h" #include "../core/slang-platform.h" #include "../core/slang-common.h" @@ -45,16 +46,16 @@ private: static DefaultSharedLibraryLoader s_singleton; }; -class DefaultSharedLibrary : public ISlangSharedLibrary, public RefObject +class DefaultSharedLibrary : public ISlangSharedLibrary, public ComBaseObject { public: SLANG_CLASS_GUID(0xe7f2597b, 0xf803, 0x4b6e, { 0xaf, 0x8b, 0xcb, 0xe3, 0xa2, 0x21, 0xfd, 0x5a }) // ISlangUnknown - virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; - SLANG_REF_OBJECT_IUNKNOWN_ADD_REF - SLANG_REF_OBJECT_IUNKNOWN_RELEASE - + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; + SLANG_COM_BASE_IUNKNOWN_ADD_REF + SLANG_COM_BASE_IUNKNOWN_RELEASE + // ISlangSharedLibrary virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) SLANG_OVERRIDE; @@ -69,7 +70,6 @@ class DefaultSharedLibrary : public ISlangSharedLibrary, public RefObject virtual ~DefaultSharedLibrary(); protected: - ISlangUnknown* getInterface(const Guid& guid); SharedLibrary::Handle m_sharedLibraryHandle = nullptr; }; |
