-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
DXFeedFramework/Native/ErrorHandling/GraalException+Ext.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// | ||
// | ||
// Copyright (C) 2024 Devexperts LLC. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
|
||
import Foundation | ||
@_implementationOnly import graal_api | ||
|
||
internal extension GraalException { | ||
static func createNew(native: UnsafeMutablePointer<dxfg_exception_t>) -> GraalException { | ||
let pointee = native.pointee | ||
let message = String(pointee: pointee.message, default: "Graall Exception") | ||
let className = String(pointee: pointee.class_name, default: "") | ||
let stackTrace = String(pointee: pointee.print_stack_trace, default: "") | ||
let gException = GraalException.fail(message: message, | ||
className: className, | ||
stack: stackTrace) | ||
return gException | ||
} | ||
|
||
func toNative() -> UnsafeMutablePointer<dxfg_exception_t>? { | ||
switch self { | ||
case .fail(message: let message, className: let className, stack: let stack): | ||
let exception = UnsafeMutablePointer<dxfg_exception_t>.allocate(capacity: 1) | ||
var pointee = exception.pointee | ||
pointee.class_name = className.toCStringRef() | ||
pointee.message = message.toCStringRef() | ||
pointee.print_stack_trace = stack.toCStringRef() | ||
exception.pointee = pointee | ||
return exception | ||
default: | ||
return nil | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// | ||
// | ||
// Copyright (C) 2024 Devexperts LLC. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
|
||
import Foundation | ||
@_implementationOnly import graal_api | ||
|
||
class NativePromise { | ||
public typealias PromiseHandler = (_: NativePromise) -> Void | ||
|
||
let promise: UnsafeMutablePointer<dxfg_promise_t>? | ||
private static let mapper = EventMapper() | ||
|
||
private class WeakPromises: WeakBox<PromiseHandler> { } | ||
private static let listeners = ConcurrentArray<WeakPromises>() | ||
|
||
static let listenerCallback: dxfg_promise_handler_function = { _, promise, context in | ||
if let context = context { | ||
let listener: AnyObject = bridge(ptr: context) | ||
if let weakListener = listener as? WeakPromises { | ||
guard let listener = weakListener.value else { | ||
return | ||
} | ||
let native = NativePromise(promise: promise) | ||
listener(native) | ||
NativePromise.listeners.removeAll(where: { | ||
return $0 === weakListener | ||
}) | ||
} | ||
} | ||
} | ||
|
||
deinit { | ||
if let promise = promise { | ||
let thread = currentThread() | ||
_ = try? ErrorCheck.nativeCall( | ||
thread, | ||
dxfg_JavaObjectHandler_release(thread, | ||
&(promise.pointee.handler))) | ||
} | ||
} | ||
|
||
init(promise: UnsafeMutablePointer<dxfg_promise_t>?) { | ||
self.promise = promise | ||
} | ||
|
||
func getResult() -> MarketEvent? { | ||
return nil | ||
} | ||
|
||
func hasResult() -> Bool { | ||
let thread = currentThread() | ||
if let result = try? ErrorCheck.nativeCall(thread, dxfg_Promise_hasResult(thread, promise)) { | ||
return result == 1 | ||
} else { | ||
return false | ||
} | ||
} | ||
|
||
func hasException() -> Bool { | ||
let thread = currentThread() | ||
if let result = try? ErrorCheck.nativeCall(thread, dxfg_Promise_hasException(thread, promise)) { | ||
return result == 1 | ||
} else { | ||
return false | ||
} | ||
} | ||
|
||
func isCancelled() -> Bool { | ||
let thread = currentThread() | ||
if let result = try? ErrorCheck.nativeCall(thread, dxfg_Promise_isCancelled(thread, promise)) { | ||
return result == 1 | ||
} else { | ||
return false | ||
} | ||
} | ||
|
||
func getException() -> GraalException? { | ||
let thread = currentThread() | ||
if let nativeException = try? ErrorCheck.nativeCall(thread, dxfg_Promise_getException(thread, promise)) { | ||
defer { | ||
_ = try? ErrorCheck.nativeCall(thread, dxfg_Exception_release(thread, nativeException)) | ||
} | ||
let exception = GraalException.createNew(native: nativeException) | ||
return exception | ||
} | ||
return nil | ||
} | ||
|
||
func await() throws -> MarketEvent? { | ||
let thread = currentThread() | ||
try ErrorCheck.nativeCall(thread, dxfg_Promise_await(thread, promise)) | ||
return nil | ||
} | ||
|
||
func await(millis timeOut: Int32) throws -> MarketEvent? { | ||
let thread = currentThread() | ||
try ErrorCheck.nativeCall(thread, dxfg_Promise_await2(thread, promise, timeOut)) | ||
return nil | ||
} | ||
|
||
func awaitWithoutException(millis timeOut: Int32) { | ||
let thread = currentThread() | ||
_ = try? ErrorCheck.nativeCall(thread, dxfg_Promise_awaitWithoutException(thread, promise, timeOut)) | ||
} | ||
|
||
func cancel() { | ||
let thread = currentThread() | ||
_ = try? ErrorCheck.nativeCall(thread, dxfg_Promise_cancel(thread, promise)) | ||
} | ||
|
||
func complete(result: MarketEvent) throws { | ||
let thread = currentThread() | ||
let nativeEvent = try NativePromise.mapper.toNative(event: result) | ||
try ErrorCheck.nativeCall(thread, dxfg_Promise_EventType_complete(thread, promise, nativeEvent)) | ||
} | ||
|
||
func completeExceptionally(_ exception: GraalException) throws { | ||
if let nativeException = exception.toNative() { | ||
let thread = currentThread() | ||
try ErrorCheck.nativeCall(thread, dxfg_Promise_completeExceptionally(thread, promise, nativeException)) | ||
} else { | ||
throw ArgumentException.exception("Coudln't convert to native exception") | ||
} | ||
} | ||
|
||
func whenDone(handler: @escaping NativePromise.PromiseHandler) { | ||
let thread = currentThread() | ||
let weakListener = WeakPromises(value: handler) | ||
NativePromise.listeners.append(newElement: weakListener) | ||
let voidPtr = bridge(obj: weakListener) | ||
_ = try? ErrorCheck.nativeCall(thread, | ||
dxfg_Promise_whenDone(thread, | ||
promise, | ||
NativePromise.listenerCallback, | ||
voidPtr)) | ||
} | ||
|
||
static func completed(result: MarketEvent) -> NativePromise? { | ||
let thread = currentThread() | ||
let promise = UnsafeMutablePointer<dxfg_promise_t>.allocate(capacity: 1) | ||
if let nativeEvent = try? NativePromise.mapper.toNative(event: result) { | ||
let handler = nativeEvent.withMemoryRebound(to: dxfg_java_object_handler.self, capacity: 1) { pointer in | ||
return pointer | ||
} | ||
let result = try? ErrorCheck.nativeCall(thread, dxfg_Promise_completed(thread, promise, handler)) | ||
return NativePromise(promise: result) | ||
} | ||
return nil | ||
} | ||
|
||
static func failed(exception: GraalException) -> NativePromise? { | ||
let thread = currentThread() | ||
let promise = UnsafeMutablePointer<dxfg_promise_t>.allocate(capacity: 1) | ||
if let nativeEvent = exception.toNative() { | ||
let result = try? ErrorCheck.nativeCall(thread, dxfg_Promise_failed(thread, promise, nativeEvent)) | ||
return NativePromise(promise: result) | ||
} | ||
return nil | ||
} | ||
|
||
static func allOf(promises: [NativePromise]) throws -> NativePromise? { | ||
let promiseList = UnsafeMutablePointer<dxfg_promise_list>.allocate(capacity: 1) | ||
let nativeList = UnsafeMutablePointer<dxfg_java_object_handler_list>.allocate(capacity: 1) | ||
let classes = UnsafeMutablePointer<UnsafeMutablePointer<dxfg_java_object_handler>?> | ||
.allocate(capacity: promises.count) | ||
var iterator = classes | ||
for code in promises { | ||
code.promise?.withMemoryRebound(to: dxfg_java_object_handler.self, capacity: 1, { pointer in | ||
iterator.initialize(to: pointer) | ||
iterator = iterator.successor() | ||
}) | ||
} | ||
nativeList.pointee.size = Int32(promises.count) | ||
nativeList.pointee.elements = classes | ||
promiseList.pointee.list = nativeList.pointee | ||
|
||
let thread = currentThread() | ||
let result = try ErrorCheck.nativeCall(thread, dxfg_Promises_allOf(thread, promiseList)) | ||
return NativePromise(promise: result) | ||
} | ||
} |
Oops, something went wrong.