};
// MachineLearningSingle::openModelAsync()
+var ValidOpenModelAsyncCallbackErrors = [
+ 'InvalidValuesError',
+ 'NotFoundError',
+ 'NotSupportedError',
+ 'AbortError'
+];
+var ValidOpenModelAsyncExceptions = ['TypeMismatchError', 'SecurityError', 'AbortError'];
+MachineLearningSingle.prototype.openModelAsync = function() {
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'modelPath',
+ type: types_.STRING
+ },
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'inTensorsInfo',
+ type: types_.PLATFORM_OBJECT,
+ values: TensorsInfo,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'outTensorsInfo',
+ type: types_.PLATFORM_OBJECT,
+ values: TensorsInfo,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'fwType',
+ type: types_.ENUM,
+ values: Object.keys(NNFWType),
+ optional: true
+ },
+ {
+ name: 'hwType',
+ type: types_.ENUM,
+ values: Object.keys(HWType),
+ optional: true
+ },
+ {
+ name: 'isDynamicMode',
+ type: types_.BOOLEAN,
+ optional: true
+ }
+ ]);
+ try {
+ // get normalized URI of a file
+ args.modelPath = tizen.filesystem.toURI(args.modelPath);
+ } catch (e) {
+ setTimeout(function() {
+ native_.callIfPossible(
+ args.errorCallback,
+ new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path is invalid')
+ );
+ }, 0);
+ return;
+ }
-// OpenModelSuccessCallback
+ var nativeArgs = {
+ modelPath: args.modelPath,
+ inTensorsInfo: args.inTensorsInfo ? args.inTensorsInfo._id : NO_ID,
+ outTensorsInfo: args.outTensorsInfo ? args.outTensorsInfo._id : NO_ID,
+ fwType: args.fwType ? args.fwType : 'ANY',
+ hwType: args.hwType ? args.hwType : 'ANY',
+ isDynamicMode: args.isDynamicMode ? args.isDynamicMode : false,
+ async: true
+ };
+
+ var callback = function(result) {
+ if (native_.isFailure(result)) {
+ native_.callIfPossible(
+ args.errorCallback,
+ native_.getErrorObjectAndValidate(
+ result,
+ ValidOpenModelAsyncCallbackErrors,
+ AbortError
+ )
+ );
+ } else {
+ args.successCallback(new SingleShot(result.id));
+ }
+ };
+
+ var result = native_.call('MLSingleManagerOpenModel', nativeArgs, callback);
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObjectAndValidate(
+ result,
+ ValidOpenModelAsyncExceptions,
+ AbortError
+ );
+ }
+};
// SingleShot interface (input & output)
var ValidInputExceptions = ['TypeMismatchError', 'AbortError'];
// Single API begin
REGISTER_METHOD(MLSingleManagerOpenModel);
- // MachineLearningSingle::openModelAsync()
- // OpenModelSuccessCallback
REGISTER_METHOD(MLSingleShotGetTensorsInfo);
REGISTER_METHOD(MLSingleShotSetInputInfo);
// SingleShot::invoke()
MlInstance::~MlInstance() {
ScopeLogger();
+ worker_.stop();
}
TensorsInfoManager& MlInstance::GetTensorsInfoManager() {
("Could not create new TensorsInfo handle"));
return;
}
- out["id"] = picojson::value(static_cast<double>(tensorsInfo->Id()));
+ out[kId] = picojson::value(static_cast<double>(tensorsInfo->Id()));
ReportSuccess(out);
}
const std::string kHwType = "hwType";
const std::string kIsDynamicMode = "isDynamicMode";
const std::string kValue = "value";
+const std::string kCallbackId = "callbackId";
+const std::string kAsync = "async";
const int kNoId = -1;
} // namespace
CHECK_ARGS(args, kIsDynamicMode, bool, out);
const auto& model_path = common::tools::ConvertUriToPath(args.get(kModelPath).get<std::string>());
- PlatformResult result = common::tools::CheckFileAvailability(model_path);
- if (!result) {
- LogAndReportError(
- PlatformResult(ErrorCode::NOT_FOUND_ERR, "File does not exist or is not accessible"), &out,
- ("File does not exist or is not accessible: %s", model_path.c_str()));
- return;
- }
+ CHECK_STORAGE_ACCESS(model_path, &out);
TensorsInfo* in_tensors_info = nullptr;
auto inTensorId = static_cast<int>(args.get(kInTensorsInfo).get<double>());
}
ml_nnfw_type_e nnfw_e = ML_NNFW_TYPE_ANY;
- result = types::NNFWTypeEnum.getValue(args.get(kFwType).get<std::string>(), &nnfw_e);
+ PlatformResult result =
+ types::NNFWTypeEnum.getValue(args.get(kFwType).get<std::string>(), &nnfw_e);
if (!result) {
LogAndReportError(result, &out);
return;
auto is_dynamic_mode = args.get(kIsDynamicMode).get<bool>();
- int res_id = -1;
- result = single_manager_.OpenModel(model_path, in_tensors_info, out_tensors_info, nnfw_e, hw_e,
- is_dynamic_mode, &res_id);
- if (!result) {
- ReportError(result, &out);
- return;
- }
+ auto logic = [this, model_path, in_tensors_info, out_tensors_info, nnfw_e, hw_e,
+ is_dynamic_mode](decltype(out) out) {
+ PlatformResult result = common::tools::CheckFileAvailability(model_path);
+ if (!result) {
+ LogAndReportError(
+ PlatformResult(ErrorCode::NOT_FOUND_ERR, "File does not exist or is not accessible"),
+ &out, ("File does not exist or is not accessible: %s", model_path.c_str()));
+ return;
+ }
- out["id"] = picojson::value(static_cast<double>(res_id));
- ReportSuccess(out);
-}
+ int res_id = -1;
+ result = single_manager_.OpenModel(model_path, in_tensors_info, out_tensors_info, nnfw_e, hw_e,
+ is_dynamic_mode, &res_id);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
-// MachineLearningSingle::openModelAsync()
+ out[kId] = picojson::value(static_cast<double>(res_id));
+ ReportSuccess(out);
+ };
-// OpenModelSuccessCallback
+ bool async =
+ (args.contains(kAsync) && args.get(kAsync).is<bool>()) ? args.get(kAsync).get<bool>() : false;
+
+ if (!async) {
+ logic(out);
+ } else {
+ // Async logic
+ CHECK_ARGS(args, kCallbackId, double, out);
+ double callback_id = args.get(kCallbackId).get<double>();
+ this->worker_.add_job([this, callback_id, logic] {
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& async_out = response.get<picojson::object>();
+ async_out[kCallbackId] = picojson::value(callback_id);
+ logic(async_out);
+ this->PostMessage(response.serialize().c_str());
+ });
+
+ // Sync return
+ ReportSuccess(out);
+ }
+}
// SingleShot input/output
// TODO move to the up section with field names
return;
}
- out["id"] = picojson::value(static_cast<double>(res_id));
+ out[kId] = picojson::value(static_cast<double>(res_id));
ReportSuccess(out);
}
#define ML_ML_INSTANCE_H_
#include "common/extension.h"
+#include "common/worker.h"
#include "ml/ml_pipeline_manager.h"
#include "ml/ml_single_manager.h"
*/
TensorsInfoManager tensors_info_manager_;
TensorsDataManager tensors_data_manager_;
+ common::Worker worker_;
// Common ML API end
// Single API begin
SingleManager single_manager_;
void MLSingleManagerOpenModel(const picojson::value& args, picojson::object& out);
- // MachineLearningSingle::openModelAsync()
- // OpenModelSuccessCallback
void MLSingleShotGetTensorsInfo(const picojson::value& args, picojson::object& out);
void MLSingleShotSetInputInfo(const picojson::value& args, picojson::object& out);
// SingleShot::invoke()
return util::ToPlatformResult(ret, "Failed to open model");
}
+ std::lock_guard<std::mutex> singles_lock(singles_mutex_);
int id = nextId_++;
singles_[id] = std::make_unique<SingleShot>(id, handle);
*res_id = id;
return PlatformResult{};
}
-// MachineLearningSingle::openModelAsync()
-// OpenModelSuccessCallback
// SingleShot input
SingleShot* SingleManager::GetSingleShot(int id) {
ScopeLogger("id: %d", id);
+ std::lock_guard<std::mutex> singles_lock(singles_mutex_);
if (singles_.end() != singles_.find(id)) {
return singles_[id].get();
}
#ifndef ML_ML_SINGLE_MANAGER_H_
#define ML_ML_SINGLE_MANAGER_H_
+#include <mutex>
+
#include "common/platform_result.h"
#include "ml_singleshot.h"
private:
int nextId_;
std::map<int, std::unique_ptr<SingleShot>> singles_;
+ std::mutex singles_mutex_;
TensorsInfoManager* tim_;
SingleShot* GetSingleShot(int id);
};