Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/sphinx/tutorial/resources.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ example:
:end-before: _sphinx_tag_tut_get_allocator_end
:language: C++

If you would prefer to avoid exceptions when an allocator is not available,
you can instead use :func:`umpire::ResourceManager::tryGetAllocator`, which
returns a ``std::optional<umpire::Allocator>`` that is empty when the
requested allocator cannot be found:

.. code-block:: cpp

auto& rm = umpire::ResourceManager::getInstance();
auto maybe_allocator = rm.tryGetAllocator("HOST");

if (maybe_allocator) {
auto allocator = *maybe_allocator;
// use allocator
}

Note that since every allocator supports the same calls, no matter which resource
it is for, this means we can run the same code for all the resources available in
the system.
Expand Down
23 changes: 23 additions & 0 deletions src/umpire/ResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,29 @@ strategy::AllocationStrategy* ResourceManager::getAllocationStrategy(const std::
return m_allocators_by_name[name];
}

std::optional<Allocator> ResourceManager::tryGetAllocator(const std::string& name)
{
UMPIRE_LOG(Debug, "(\"" << name << "\")");

resource::MemoryResourceRegistry& registry{resource::MemoryResourceRegistry::getInstance()};
auto resource_names = registry.getResourceNames();

auto allocator = m_allocators_by_name.find(name);
if (allocator == m_allocators_by_name.end()) {
auto resource_name = std::find(resource_names.begin(), resource_names.end(), name);
if (resource_name != std::end(resource_names)) {
makeResource(name);
allocator = m_allocators_by_name.find(name);
}
}

if (allocator == m_allocators_by_name.end()) {
return std::nullopt;
}

return Allocator{allocator->second};
}

Allocator ResourceManager::getAllocator(const std::string& name)
{
UMPIRE_LOG(Debug, "(\"" << name << "\")");
Expand Down
9 changes: 9 additions & 0 deletions src/umpire/ResourceManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <list>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -67,6 +68,14 @@ class ResourceManager {
*/
Allocator getAllocator(const std::string& name);

/*!
* \brief Try to get the Allocator with the given name.
*
* This function returns an empty optional if the allocator does not exist
* or cannot be created, instead of throwing an exception.
*/
std::optional<Allocator> tryGetAllocator(const std::string& name);

Allocator getAllocator(const char* name);

/*!
Expand Down
12 changes: 12 additions & 0 deletions tests/integration/allocator_integration_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,18 @@ TEST(Allocator, registerAllocator)
ASSERT_FALSE(rm.isAllocator("BANANAS"));
}

TEST(Allocator, TryGetAllocator)
{
auto& rm = umpire::ResourceManager::getInstance();

auto host_allocator = rm.tryGetAllocator("HOST");
ASSERT_TRUE(host_allocator.has_value());
EXPECT_EQ(std::string{"HOST"}, host_allocator->getName());

auto bad_allocator = rm.tryGetAllocator("BANANAS");
EXPECT_FALSE(bad_allocator.has_value());
}

TEST(Allocator, GetSetDefault)
{
auto& rm = umpire::ResourceManager::getInstance();
Expand Down
Loading