blob: 410265eb3801c8d20fe5653e9b0c50ac08754559 [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
48 return BackendId(m_BackendIdFunction());
49}
50
51BackendVersion DynamicBackend::GetBackendVersion()
52{
53 if (m_BackendVersionFunction == nullptr)
54 {
55 throw RuntimeException("GetBackendVersion error: invalid function pointer");
56 }
57
58 uint32_t major = 0;
59 uint32_t minor = 0;
60 m_BackendVersionFunction(&major, &minor);
61
62 return BackendVersion{ major, minor };
63}
64
65IBackendInternalUniquePtr DynamicBackend::GetBackend()
66{
67 if (m_BackendFactoryFunction == nullptr)
68 {
69 throw RuntimeException("GetBackend error: invalid function pointer");
70 }
71
72 auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
73 if (backendPointer == nullptr)
74 {
75 throw RuntimeException("GetBackend error: backend instance must not be null");
76 }
77
78 return std::unique_ptr<IBackendInternal>(backendPointer);
79}
80
81template<typename BackendFunctionType>
82BackendFunctionType DynamicBackend::SetFunctionPointer(const std::string& backendFunctionName)
83{
84 if (m_Handle == nullptr)
85 {
86 throw RuntimeException("SetFunctionPointer error: invalid shared object handle");
87 }
88
89 if (backendFunctionName.empty())
90 {
91 throw RuntimeException("SetFunctionPointer error: backend function name must not be empty");
92 }
93
94 // This call will throw in case of error
95 auto functionPointer = DynamicBackendUtils::GetEntryPoint<BackendFunctionType>(m_Handle.get(),
96 backendFunctionName.c_str());
97 if (!functionPointer)
98 {
99 throw RuntimeException("SetFunctionPointer error: invalid backend function pointer returned");
100 }
101
102 return functionPointer;
103}
104
105} // namespace armnn