blob: a9f1203a78896ebda60eedf6110989fcff6ee88f [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build java android
package context
import (
"errors"
"unsafe"
"v.io/v23/context"
jutil "v.io/x/jni/util"
)
// #include "jni.h"
// #include <stdlib.h>
import "C"
var (
classSign = jutil.ClassSign("java.lang.Class")
doneReasonSign = jutil.ClassSign("io.v.v23.context.VContext$DoneReason")
// Global reference for io.v.v23.context.VContext class.
jVContextClass jutil.Class
// Global reference for io.v.v23.context.VContext$DoneReason
jDoneReasonClass jutil.Class
)
// Init initializes the JNI code with the given Java environment. This method
// must be called from the main Java thread.
func Init(env jutil.Env) error {
// Cache global references to all Java classes used by the package. This is
// necessary because JNI gets access to the class loader only in the system
// thread, so we aren't able to invoke FindClass in other threads.
var err error
jVContextClass, err = jutil.JFindClass(env, "io/v/v23/context/VContext")
if err != nil {
return err
}
jDoneReasonClass, err = jutil.JFindClass(env, "io/v/v23/context/VContext$DoneReason")
if err != nil {
return err
}
return nil
}
//export Java_io_v_v23_context_VContext_nativeCreate
func Java_io_v_v23_context_VContext_nativeCreate(jenv *C.JNIEnv, jVContext C.jclass) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
ctx, _ := context.RootContext()
jContext, err := JavaContext(env, ctx, nil)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jContext))
}
//export Java_io_v_v23_context_VContext_nativeCancel
func Java_io_v_v23_context_VContext_nativeCancel(jenv *C.JNIEnv, jVContext C.jobject, goCancelRef C.jlong) {
(*(*context.CancelFunc)(jutil.GoRefValue(jutil.Ref(goCancelRef))))()
}
//export Java_io_v_v23_context_VContext_nativeIsCanceled
func Java_io_v_v23_context_VContext_nativeIsCanceled(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong) C.jboolean {
if (*(*context.T)(jutil.GoRefValue(jutil.Ref(goRef)))).Err() == nil {
return C.JNI_FALSE
}
return C.JNI_TRUE
}
//export Java_io_v_v23_context_VContext_nativeDeadline
func Java_io_v_v23_context_VContext_nativeDeadline(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
d, ok := (*(*context.T)(jutil.GoRefValue(jutil.Ref(goRef)))).Deadline()
if !ok {
return nil
}
jDeadline, err := jutil.JTime(env, d)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jDeadline))
}
//export Java_io_v_v23_context_VContext_nativeOnDone
func Java_io_v_v23_context_VContext_nativeOnDone(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
ctx := (*(*context.T)(jutil.GoRefValue(jutil.Ref(goRef))))
c := ctx.Done()
if c == nil {
jutil.CallbackOnFailure(env, jCallback, errors.New("Context isn't cancelable"))
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
<-c
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jReason, err := JavaContextDoneReason(env, ctx.Err())
if err != nil {
return jutil.NullObject, err
}
// Must grab a global reference as we free up the env and all local references that come along
// with it.
return jutil.NewGlobalRef(env, jReason), nil // Un-refed in DoAsyncCall
})
}
//export Java_io_v_v23_context_VContext_nativeValue
func Java_io_v_v23_context_VContext_nativeValue(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong, jKeySign C.jstring) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
key := goContextKey(jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jKeySign)))))
value := (*(*context.T)(jutil.GoRefValue(jutil.Ref(goRef)))).Value(key)
jValue, err := JavaContextValue(env, value)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jValue))
}
//export Java_io_v_v23_context_VContext_nativeWithCancel
func Java_io_v_v23_context_VContext_nativeWithCancel(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
ctx, cancelFunc := context.WithCancel((*context.T)(jutil.GoRefValue(jutil.Ref(goRef))))
jCtx, err := JavaContext(env, ctx, cancelFunc)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jCtx))
}
//export Java_io_v_v23_context_VContext_nativeWithDeadline
func Java_io_v_v23_context_VContext_nativeWithDeadline(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong, jDeadline C.jobject) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
deadline, err := jutil.GoTime(env, jutil.Object(uintptr(unsafe.Pointer(jDeadline))))
if err != nil {
jutil.JThrowV(env, err)
return nil
}
ctx, cancelFunc := context.WithDeadline((*context.T)(jutil.GoRefValue(jutil.Ref(goRef))), deadline)
jCtx, err := JavaContext(env, ctx, cancelFunc)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jCtx))
}
//export Java_io_v_v23_context_VContext_nativeWithTimeout
func Java_io_v_v23_context_VContext_nativeWithTimeout(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong, jTimeout C.jobject) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
timeout, err := jutil.GoDuration(env, jutil.Object(uintptr(unsafe.Pointer(jTimeout))))
if err != nil {
jutil.JThrowV(env, err)
return nil
}
ctx, cancelFunc := context.WithTimeout((*context.T)(jutil.GoRefValue(jutil.Ref(goRef))), timeout)
jCtx, err := JavaContext(env, ctx, cancelFunc)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jCtx))
}
//export Java_io_v_v23_context_VContext_nativeWithValue
func Java_io_v_v23_context_VContext_nativeWithValue(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong, goCancelRef C.jlong, jKeySign C.jstring, jValue C.jobject) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
key := goContextKey(jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jKeySign)))))
value, err := GoContextValue(env, jutil.Object(uintptr(unsafe.Pointer(jValue))))
if err != nil {
jutil.JThrowV(env, err)
return nil
}
ctx := context.WithValue((*context.T)(jutil.GoRefValue(jutil.Ref(goRef))), key, value)
var cancel context.CancelFunc
if goCancelRef != 0 {
cancel = (*(*context.CancelFunc)(jutil.GoRefValue(jutil.Ref(goCancelRef))))
}
jCtx, err := JavaContext(env, ctx, cancel)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jCtx))
}
//export Java_io_v_v23_context_VContext_nativeFinalize
func Java_io_v_v23_context_VContext_nativeFinalize(jenv *C.JNIEnv, jVContext C.jobject, goRef C.jlong, goCancelRef C.jlong) {
jutil.GoDecRef(jutil.Ref(goRef))
if jutil.Ref(goCancelRef) != jutil.NullRef {
jutil.GoDecRef(jutil.Ref(goCancelRef))
}
}