10
10
#import < ETCoreMLModel.h>
11
11
#import < ETCoreMLModelManager.h>
12
12
#import < ETCoreMLStrings.h>
13
- #import < atomic>
14
13
#import < backend_delegate.h>
15
14
#import < model_event_logger.h>
16
15
#import < multiarray.h>
@@ -88,6 +87,153 @@ MLComputeUnits get_compute_units(const Buffer& buffer) {
88
87
}
89
88
} // namespace
90
89
90
+ @interface ETCoreMLModelManagerDelegate : NSObject
91
+
92
+ - (instancetype )init NS_UNAVAILABLE;
93
+
94
+ + (instancetype )new NS_UNAVAILABLE;
95
+
96
+ - (instancetype )initWithConfig : (BackendDelegate::Config)config NS_DESIGNATED_INITIALIZER;
97
+
98
+ - (BOOL )loadAndReturnError : (NSError * _Nullable __autoreleasing *)error ;
99
+
100
+ - (void )loadAsynchronously ;
101
+
102
+ - (ModelHandle*)loadModelFromAOTData : (NSData *)data
103
+ configuration : (MLModelConfiguration*)configuration
104
+ error : (NSError * __autoreleasing*)error ;
105
+
106
+ - (BOOL )executeModelWithHandle : (ModelHandle*)handle
107
+ argsVec : (const std::vector<executorchcoreml::MultiArray>&)argsVec
108
+ loggingOptions : (const executorchcoreml::ModelLoggingOptions&)loggingOptions
109
+ eventLogger : (const executorchcoreml::ModelEventLogger* _Nullable)eventLogger
110
+ error : (NSError * __autoreleasing*)error ;
111
+
112
+ - (BOOL )unloadModelWithHandle : (ModelHandle*)handle ;
113
+
114
+ - (BOOL )purgeModelsCacheAndReturnError : (NSError * _Nullable __autoreleasing *)error ;
115
+
116
+ @property (assign , readonly , nonatomic ) BackendDelegate::Config config;
117
+ @property (strong , readonly , nonatomic ) dispatch_queue_t syncQueue;
118
+ @property (strong , nonatomic , nullable ) ETCoreMLModelManager *impl;
119
+ @property (assign , readonly , nonatomic ) BOOL isAvailable;
120
+
121
+ @end
122
+
123
+ @implementation ETCoreMLModelManagerDelegate
124
+
125
+ - (instancetype )initWithConfig : (BackendDelegate::Config)config {
126
+ self = [super init ];
127
+ if (self) {
128
+ _config = std::move (config);
129
+ _syncQueue = dispatch_queue_create (" com.executorchcoreml.modelmanagerdelegate.sync" , DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
130
+ }
131
+
132
+ return self;
133
+ }
134
+
135
+ - (BOOL )_loadAndReturnError : (NSError * _Nullable __autoreleasing *)error {
136
+ if (self.impl != nil ) {
137
+ return YES ;
138
+ }
139
+
140
+ ETCoreMLAssetManager *assetManager = create_asset_manager (ETCoreMLStrings.assetsDirectoryPath ,
141
+ ETCoreMLStrings.trashDirectoryPath ,
142
+ ETCoreMLStrings.databaseDirectoryPath ,
143
+ ETCoreMLStrings.databaseName ,
144
+ self.config .max_models_cache_size ,
145
+ error);
146
+ if (!assetManager) {
147
+ return NO ;
148
+ }
149
+
150
+ ETCoreMLModelManager *modelManager = [[ETCoreMLModelManager alloc ] initWithAssetManager: assetManager];
151
+ if (!modelManager) {
152
+ return NO ;
153
+ }
154
+
155
+ self.impl = modelManager;
156
+
157
+ if (self.config .should_prewarm_asset ) {
158
+ [modelManager prewarmRecentlyUsedAssetsWithMaxCount: 1 ];
159
+ }
160
+
161
+ return YES ;
162
+ }
163
+
164
+ - (BOOL )loadAndReturnError : (NSError * _Nullable __autoreleasing *)error {
165
+ __block NSError *localError = nil ;
166
+ __block BOOL result = NO ;
167
+ dispatch_sync (self.syncQueue , ^{
168
+ result = [self _loadAndReturnError: &localError];
169
+ });
170
+
171
+ if (error) {
172
+ *error = localError;
173
+ }
174
+
175
+ return result;
176
+ }
177
+
178
+ - (void )loadAsynchronously {
179
+ dispatch_async (self.syncQueue , ^{
180
+ (void )[self _loadAndReturnError: nil ];
181
+ });
182
+ }
183
+
184
+ - (ModelHandle*)loadModelFromAOTData : (NSData *)data
185
+ configuration : (MLModelConfiguration*)configuration
186
+ error : (NSError * __autoreleasing*)error {
187
+ if (![self loadAndReturnError: error]) {
188
+ return nil ;
189
+ }
190
+
191
+ return [self .impl loadModelFromAOTData: data
192
+ configuration: configuration
193
+ error: error];
194
+ }
195
+
196
+ - (BOOL )executeModelWithHandle : (ModelHandle*)handle
197
+ argsVec : (const std::vector<executorchcoreml::MultiArray>&)argsVec
198
+ loggingOptions : (const executorchcoreml::ModelLoggingOptions&)loggingOptions
199
+ eventLogger : (const executorchcoreml::ModelEventLogger* _Nullable)eventLogger
200
+ error : (NSError * __autoreleasing*)error {
201
+ assert (self.impl != nil && " Impl must not be nil" );
202
+ return [self .impl executeModelWithHandle: handle
203
+ argsVec: argsVec
204
+ loggingOptions: loggingOptions
205
+ eventLogger: eventLogger
206
+ error: error];
207
+ }
208
+
209
+ - (nullable ETCoreMLModel*)modelWithHandle : (ModelHandle*)handle {
210
+ assert (self.impl != nil && " Impl must not be nil" );
211
+ return [self .impl modelWithHandle: handle];
212
+ }
213
+
214
+ - (BOOL )unloadModelWithHandle : (ModelHandle*)handle {
215
+ assert (self.impl != nil && " Impl must not be nil" );
216
+ return [self .impl unloadModelWithHandle: handle];
217
+ }
218
+
219
+ - (BOOL )purgeModelsCacheAndReturnError : (NSError * _Nullable __autoreleasing *)error {
220
+ if (![self loadAndReturnError: error]) {
221
+ return NO ;
222
+ }
223
+
224
+ return [self .impl purgeModelsCacheAndReturnError: error];;
225
+ }
226
+
227
+ - (BOOL )isAvailable {
228
+ if (![self loadAndReturnError: nil ]) {
229
+ return NO ;
230
+ }
231
+
232
+ return YES ;
233
+ }
234
+
235
+ @end
236
+
91
237
namespace executorchcoreml {
92
238
93
239
std::string BackendDelegate::ErrorCategory::message (int code) const {
@@ -114,20 +260,9 @@ MLComputeUnits get_compute_units(const Buffer& buffer) {
114
260
class BackendDelegateImpl : public BackendDelegate {
115
261
public:
116
262
explicit BackendDelegateImpl (const Config& config) noexcept
117
- :BackendDelegate(), config_(config) {
118
- NSError *localError = nil ;
119
- ETCoreMLAssetManager *asset_manager = create_asset_manager (ETCoreMLStrings.assetsDirectoryPath ,
120
- ETCoreMLStrings.trashDirectoryPath ,
121
- ETCoreMLStrings.databaseDirectoryPath ,
122
- ETCoreMLStrings.databaseName ,
123
- config.max_models_cache_size ,
124
- &localError);
125
-
126
- model_manager_ = (asset_manager != nil ) ? [[ETCoreMLModelManager alloc ] initWithAssetManager: asset_manager] : nil ;
127
- if (model_manager_ != nil && config_.should_prewarm_asset ) {
128
- [model_manager_ prewarmRecentlyUsedAssetsWithMaxCount: 1 ];
129
- }
130
- available_.store (model_manager_ != nil , std::memory_order_seq_cst);
263
+ :BackendDelegate(), model_manager_([[ETCoreMLModelManagerDelegate alloc ] initWithConfig: config])
264
+ {
265
+ [model_manager_ loadAsynchronously ];
131
266
}
132
267
133
268
BackendDelegateImpl (BackendDelegateImpl const &) = delete ;
@@ -142,11 +277,6 @@ explicit BackendDelegateImpl(const Config& config) noexcept
142
277
ModelHandle *modelHandle = [model_manager_ loadModelFromAOTData: data
143
278
configuration: configuration
144
279
error: &localError];
145
- if (modelHandle && config_.should_prewarm_model ) {
146
- NSError *localError = nil ;
147
- [model_manager_ prewarmModelWithHandle: modelHandle error: &localError];
148
- }
149
-
150
280
return modelHandle;
151
281
}
152
282
@@ -158,7 +288,7 @@ bool execute(Handle* handle,
158
288
NSError *error = nil ;
159
289
if (![model_manager_ executeModelWithHandle: handle
160
290
argsVec: args
161
- loggingOptions: logging_options
291
+ loggingOptions: logging_options
162
292
eventLogger: event_logger
163
293
error: &error]) {
164
294
ec = static_cast <ErrorCode>(error.code );
@@ -173,7 +303,7 @@ bool is_valid_handle(Handle* handle) const noexcept override {
173
303
}
174
304
175
305
bool is_available () const noexcept override {
176
- return available_. load (std::memory_order_acquire );
306
+ return static_cast < bool >(model_manager_. isAvailable );
177
307
}
178
308
179
309
std::pair<size_t , size_t > get_num_arguments (Handle* handle) const noexcept override {
@@ -187,12 +317,11 @@ void destroy(Handle* handle) const noexcept override {
187
317
188
318
bool purge_models_cache () const noexcept override {
189
319
NSError *localError = nil ;
190
- bool result = static_cast <bool >([model_manager_.assetManager purge : &localError]);
320
+ bool result = static_cast <bool >([model_manager_ purgeModelsCacheAndReturnError : &localError]);
191
321
return result;
192
322
}
193
323
194
- ETCoreMLModelManager *model_manager_;
195
- std::atomic<bool > available_;
324
+ ETCoreMLModelManagerDelegate *model_manager_;
196
325
Config config_;
197
326
};
198
327
0 commit comments