blob: c576199e1f2e0a120ab95d7ce6335a2e78a627b9 [file] [log] [blame]
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "DynamicBackend.hpp"
7#include "DynamicBackendUtils.hpp"
8
9namespace armnn
10{
11
12DynamicBackend::DynamicBackend(const void* sharedObjectHandle)
13 : m_BackendIdFunction(nullptr)
14 , m_BackendVersionFunction(nullptr)
15 , m_BackendFactoryFunction(nullptr)
16 , m_Handle(const_cast<void*>(sharedObjectHandle), &DynamicBackendUtils::CloseHandle)
17{
18 if (m_Handle == nullptr)
19 {
20 throw InvalidArgumentException("Cannot create a DynamicBackend object from an invalid shared object handle");
21 }
22
23 // These calls will throw in case of error
24 m_BackendIdFunction = SetFunctionPointer<IdFunctionType>("GetBackendId");
25 m_BackendVersionFunction = SetFunctionPointer<VersionFunctionType>("GetVersion");
26 m_BackendFactoryFunction = SetFunctionPointer<FactoryFunctionType>("BackendFactory");
27
28 // Check that the backend is compatible with the current Backend API
29 BackendId backendId = GetBackendId();
30 BackendVersion backendVersion = GetBackendVersion();
31 if (!DynamicBackendUtils::IsBackendCompatible(backendVersion))
32 {
33 throw RuntimeException(boost::str(boost::format("The dynamic backend %1% (version %2%) is not compatible"
34 "with the current Backend API (vesion %3%)")
35 % backendId
36 % backendVersion
37 % IBackendInternal::GetApiVersion()));
38 }
39}
40
41BackendId DynamicBackend::GetBackendId()
42{
43 if (m_BackendIdFunction == nullptr)
44 {
45 throw RuntimeException("GetBackendId error: invalid function pointer");
46 }
47
Matteo Martincighbc2e2102019-07-24 14:56:13 +010048 const char* backendId = m_BackendIdFunction();
49 if (backendId == nullptr)
50 {
51 throw RuntimeException("GetBackendId error: invalid backend id");
52 }
53
54 return BackendId(backendId);
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +010055}
56
57BackendVersion DynamicBackend::GetBackendVersion()
58{
59 if (m_BackendVersionFunction == nullptr)
60 {
61 throw RuntimeException("GetBackendVersion error: invalid function pointer");
62 }
63
64 uint32_t major = 0;
65 uint32_t minor = 0;
66 m_BackendVersionFunction(&major, &minor);
67
68 return BackendVersion{ major, minor };
69}
70
71IBackendInternalUniquePtr DynamicBackend::GetBackend()
72{
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010073 // This call throws in case of error
74 return CreateBackend();
75}
76
77BackendRegistry::FactoryFunction DynamicBackend::GetFactoryFunction()
78{
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +010079 if (m_BackendFactoryFunction == nullptr)
80 {
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010081 throw RuntimeException("GetFactoryFunction error: invalid function pointer");
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +010082 }
83
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010084 return [this]() -> IBackendInternalUniquePtr
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +010085 {
Matteo Martincigh0c2b2892019-08-05 14:12:11 +010086 // This call throws in case of error
87 return CreateBackend();
88 };
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +010089}
90
91template<typename BackendFunctionType>
92BackendFunctionType DynamicBackend::SetFunctionPointer(const std::string& backendFunctionName)
93{
94 if (m_Handle == nullptr)
95 {
96 throw RuntimeException("SetFunctionPointer error: invalid shared object handle");
97 }
98
99 if (backendFunctionName.empty())
100 {
101 throw RuntimeException("SetFunctionPointer error: backend function name must not be empty");
102 }
103
104 // This call will throw in case of error
105 auto functionPointer = DynamicBackendUtils::GetEntryPoint<BackendFunctionType>(m_Handle.get(),
106 backendFunctionName.c_str());
107 if (!functionPointer)
108 {
109 throw RuntimeException("SetFunctionPointer error: invalid backend function pointer returned");
110 }
111
112 return functionPointer;
113}
114
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100115IBackendInternalUniquePtr DynamicBackend::CreateBackend()
116{
117 if (m_BackendFactoryFunction == nullptr)
118 {
119 throw RuntimeException("CreateBackend error: invalid function pointer");
120 }
121
122 auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
123 if (backendPointer == nullptr)
124 {
125 throw RuntimeException("CreateBackend error: backend instance must not be null");
126 }
127
128 return std::unique_ptr<IBackendInternal>(backendPointer);
129}
130
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +0100131} // namespace armnn