Github #273 Handle failure to initialise BackendContext in Runtime

Define CreateBackendContext to throw BackendUnavailableException
if necessary runtime components are missing.

Handle this in the constructor of Runtime by not adding those
backends to the internal DeviceSpec owned by the Runtime.

Signed-off-by: Matthew Bentham <Matthew.Bentham@arm.com>
Change-Id: Iadffb5240e32e1f105683c4d361276b92d1e720c
diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp
index 2d7269a..47c998a 100644
--- a/src/armnn/Runtime.cpp
+++ b/src/armnn/Runtime.cpp
@@ -153,7 +153,6 @@
 
 Runtime::Runtime(const CreationOptions& options)
     : m_NetworkIdCounter(0)
-    , m_DeviceSpec{BackendRegistryInstance().GetBackendIds()}
 {
     ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
 
@@ -164,12 +163,11 @@
     // goes through the backend registry
     LoadDynamicBackends(options.m_DynamicBackendsPath);
 
+    BackendIdSet supportedBackends;
     for (const auto& id : BackendRegistryInstance().GetBackendIds())
     {
         // Store backend contexts for the supported ones
-        const BackendIdSet& supportedBackends = m_DeviceSpec.GetSupportedBackends();
-        if (supportedBackends.find(id) != supportedBackends.end())
-        {
+        try {
             auto factoryFun = BackendRegistryInstance().GetFactory(id);
             auto backend = factoryFun();
             BOOST_ASSERT(backend.get() != nullptr);
@@ -182,8 +180,15 @@
             {
                 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
             }
+            supportedBackends.emplace(id);
         }
+        catch (const BackendUnavailableException&)
+        {
+            // Ignore backends which are unavailable
+        }
+
     }
+    m_DeviceSpec.AddSupportedBackends(supportedBackends);
 }
 
 Runtime::~Runtime()