Skip to content

Commit

Permalink
dev(ustring.h): string literal operator for ustring and ustringhash (A…
Browse files Browse the repository at this point in the history
…cademySoftwareFoundation#3939)

* Add string literal operators for ustring and ustringhash so you can
write: ``` "foo"_us "bar"_ush ``` Note that on Cuda (but not on the
host), this ustringhash construction is constexpr.

* Add a new `ustringhash(const char*, size_t)` constructor, which is
also constexpr on the device side.

* Mark the existing `ustringhash(string_view)` constructor as constexpr
on the device side.

We can mark those things as constexpr on the device side because on the
Cuda side, the implementation only takes the hash (which is constexpr),
and does not actually add a ustring to the table (which cannot be
constexpr). To make such declarations easy, add a new macro to
platform.h, `OIIO_DEVICE_CONSTEXPR` which is constexpr for the device,
merely inline for the host.

---------

Signed-off-by: Larry Gritz <[email protected]>
  • Loading branch information
lgritz authored Aug 21, 2023
1 parent 15750af commit 629b205
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 6 deletions.
9 changes: 9 additions & 0 deletions src/include/OpenImageIO/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,15 @@
#endif


// OIIO_DEVICE_CONSTEXPR is like OIIO_HOSTDEVICE, but it's `constexpr` only on
// the Cuda device side, and merely inline (not constexpr) on the host side.
#ifdef __CUDA_ARCH__
# define OIIO_DEVICE_CONSTEXPR __device__ constexpr
#else
# define OIIO_DEVICE_CONSTEXPR /*__host__*/ inline
#endif



// OIIO_PRETTY_FUNCTION gives a text string of the current function
// declaration.
Expand Down
46 changes: 40 additions & 6 deletions src/include/OpenImageIO/ustring.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,23 +815,41 @@ class OIIO_UTIL_API ustringhash {
}

/// Construct a ustringhash from a null-terminated C string (char *).
OIIO_HOSTDEVICE explicit ustringhash(const char* str)
OIIO_DEVICE_CONSTEXPR explicit ustringhash(const char* str)
{
#ifdef __CUDA_ARCH__
m_hash = Strutil::strhash(str); // GPU: just compute the hash
// GPU: just compute the hash. This can be constexpr!
m_hash = Strutil::strhash(str);
#else
m_hash = ustring(str).hash(); // CPU: make ustring, get its hash
// CPU: make ustring, get its hash. Note that ustring ctr can't be
// constexpr because it has to modify the internal ustring table.
m_hash = ustring(str).hash();
#endif
}

OIIO_DEVICE_CONSTEXPR explicit ustringhash(const char* str, size_t len)
{
#ifdef __CUDA_ARCH__
// GPU: just compute the hash. This can be constexpr!
m_hash = Strutil::strhash(len, str);
#else
// CPU: make ustring, get its hash. Note that ustring ctr can't be
// constexpr because it has to modify the internal ustring table.
m_hash = ustring(str, len).hash();
#endif
}

/// Construct a ustringhash from a string_view, which can be
/// auto-converted from either a std::string.
OIIO_HOSTDEVICE explicit ustringhash(string_view str)
OIIO_DEVICE_CONSTEXPR explicit ustringhash(string_view str)
{
#ifdef __CUDA_ARCH__
m_hash = Strutil::strhash(str); // GPU: just compute the hash
// GPU: just compute the hash. This can be constexpr!
m_hash = Strutil::strhash(str);
#else
m_hash = ustring(str).hash(); // CPU: make ustring, get its hash
// CPU: make ustring, get its hash. Note that ustring ctr can't be
// constexpr because it has to modify the internal ustring table.
m_hash = ustring(str).hash();
#endif
}

Expand Down Expand Up @@ -1013,6 +1031,22 @@ inline ustring::ustring(ustringhash hash)



/// ustring string literal operator
inline ustring operator""_us(const char* str, std::size_t len)
{
return ustring(str, len);
}


/// ustringhash string literal operator
OIIO_DEVICE_CONSTEXPR ustringhash operator""_ush(const char* str,
std::size_t len)
{
return ustringhash(str, len);
}



#if OIIO_VERSION_LESS(3, 0, 0)
/// Deprecated -- This is too easy to confuse with the ustringhash class. And
/// also it is unnecessary if you use std::hash<ustring>. This will be removed
Expand Down
12 changes: 12 additions & 0 deletions src/libutil/ustring_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ test_ustring()

// std::hash
OIIO_CHECK_EQUAL(std::hash<ustring> {}(foo), foo.hash());

// string literals
auto whichtype = "foo"_us;
OIIO_CHECK_EQUAL(whichtype, ustring("foo"));
OIIO_CHECK_ASSERT((std::is_same<decltype(whichtype), ustring>::value));
OIIO_CHECK_ASSERT(!(std::is_same<decltype(whichtype), const char*>::value));
}


Expand Down Expand Up @@ -227,6 +233,12 @@ test_ustringhash()

// formatting string
OIIO_CHECK_EQUAL(Strutil::fmt::format("{}", hfoo), "foo");

// string literals
auto whichtype = "foo"_ush;
OIIO_CHECK_EQUAL(whichtype, ustringhash("foo"));
OIIO_CHECK_ASSERT((std::is_same<decltype(whichtype), ustringhash>::value));
OIIO_CHECK_ASSERT(!(std::is_same<decltype(whichtype), const char*>::value));
}


Expand Down

0 comments on commit 629b205

Please sign in to comment.