summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-07-18 15:44:29 -0400
committerGitHub <noreply@github.com>2022-07-18 15:44:29 -0400
commit2e4b5770fa7e6dbf56845382706b33a22d6a025b (patch)
treee58bcb7c446fcbffc8e1dd725636dbd737d946fc
parentda8f050f9865635e5778589e1e3883b614d73266 (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.json10
-rw-r--r--docs/api-users-guide.md2
-rw-r--r--source/compiler-core/slang-downstream-compiler.cpp13
-rw-r--r--source/core/slang-com-object.h68
-rw-r--r--source/core/slang-shared-library.cpp5
-rw-r--r--source/core/slang-shared-library.h12
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;
};