Skip to content

Commit

Permalink
Add example of MultiThreadExecutor
Browse files Browse the repository at this point in the history
Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 authored and clover2123 committed Oct 30, 2023
1 parent 2bd31a2 commit 5c797fa
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 5 deletions.
1 change: 1 addition & 0 deletions build/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,37 @@
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import com.samsung.lwe.escargot.Bridge;
import com.samsung.lwe.escargot.Context;
import com.samsung.lwe.escargot.Evaluator;
import com.samsung.lwe.escargot.Globals;
import com.samsung.lwe.escargot.JavaScriptArrayObject;
import com.samsung.lwe.escargot.JavaScriptJavaCallbackFunctionObject;
import com.samsung.lwe.escargot.JavaScriptString;
import com.samsung.lwe.escargot.JavaScriptValue;
import com.samsung.lwe.escargot.Memory;
import com.samsung.lwe.escargot.VMInstance;
import com.samsung.lwe.escargot.util.MultiThreadExecutor;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Optional;

public class MainActivity extends AppCompatActivity {
Expand Down Expand Up @@ -188,6 +196,116 @@ public Optional<JavaScriptValue> callback(Context context, JavaScriptValue javaS
}).start();
}

public void runExample()
{
new Thread(() -> {
Looper.prepare();
Handler handler = new Handler(Looper.myLooper());

Globals.initializeGlobals();

VMInstance vmInstance = VMInstance.create(Optional.empty(), Optional.empty());
Context context = Context.create(vmInstance);

context.getGlobalObject().set(context, JavaScriptString.create("print"), JavaScriptJavaCallbackFunctionObject.create(context, "", 1, false, new JavaScriptJavaCallbackFunctionObject.Callback() {
@Override
public Optional<JavaScriptValue> callback(Context context, JavaScriptValue receiverValue, JavaScriptValue[] arguments) {
System.out.println(arguments[0].toString(context).get().toJavaString());
return Optional.empty();
}
}));

context.getGlobalObject().set(context, JavaScriptString.create("end"), JavaScriptJavaCallbackFunctionObject.create(context, "", 1, false, new JavaScriptJavaCallbackFunctionObject.Callback() {
@Override
public Optional<JavaScriptValue> callback(Context context, JavaScriptValue receiverValue, JavaScriptValue[] arguments) {
Looper.myLooper().quitSafely();
return Optional.empty();
}
}));

MultiThreadExecutor executor = new MultiThreadExecutor(vmInstance, new MultiThreadExecutor.WorkerThreadEndNotifier() {
@Override
public void notify(MultiThreadExecutor executor, MultiThreadExecutor.ExecutorInstance instance) {
handler.post(new Runnable() {
@Override
public void run() {
executor.pumpEventsFromThreadIfNeeds();
}
});
}
});
Bridge.register(context, "HTTP", "get", new Bridge.Adapter() {
@Override
public Optional<JavaScriptValue> callback(Context context, Optional<JavaScriptValue> data) {
String url = "";
if (data.isPresent()) {
Optional<JavaScriptString> mayBeString = data.get().toString(context);
if (mayBeString.isPresent()) {
url = mayBeString.get().toJavaString();
}
}
final String finalURL = url;
MultiThreadExecutor.ExecutorInstance instance = executor.startWorker(context, new MultiThreadExecutor.Executor() {
@Override
public MultiThreadExecutor.ResultBuilderContext run() {
try {
HttpURLConnection connection = (HttpURLConnection)new URL(finalURL).openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { // success
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();

return new MultiThreadExecutor.ResultBuilderContext(true, response.toString());
} else {
return new MultiThreadExecutor.ResultBuilderContext(false, "error HTTP return code:" + responseCode);
}
} catch (IOException e) {
return new MultiThreadExecutor.ResultBuilderContext(false, e.toString());
}
}
}, new MultiThreadExecutor.ResultBuilder() {
@Override
public JavaScriptValue build(Context scriptContext, MultiThreadExecutor.ResultBuilderContext builderContext) {
return JavaScriptString.create((String)builderContext.data());
}
});
return Optional.of(instance.promise());
}
});

Evaluator.evalScript(context, "" +
"let promise1 = HTTP.get('https://httpbin.org/get');" +
"let promise2 = HTTP.get('http://google.com');" +
"Promise.allSettled([promise1, promise2]).then(function(v) {" +
"print(JSON.stringify(v));" +
"print('http all end!');" +
"end();" +
"});", "", false);


Looper.loop();
Looper.myLooper().quit();

context = null;
vmInstance = null;

Memory.gc();
Memory.gc();
Memory.gc();
Memory.gc();
Memory.gc();

Globals.finalizeGlobals();
}).start();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -205,11 +323,11 @@ public void onClick(View v) {
}
});

(new Handler()).postDelayed(new Runnable() {
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void run() {
findViewById(R.id.button).callOnClick();
public void onClick(View v) {
runExample();
}
}, 3000);
});
}
}
6 changes: 6 additions & 0 deletions build/android/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="run"/>
<Button
android:id="@+id/button2"
android:layout_toRightOf="@id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="mt example"/>
<TextView
android:layout_below="@+id/button"
android:layout_width="match_parent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Optional;

Expand Down Expand Up @@ -1690,4 +1695,87 @@ public JavaScriptValue build(Context scriptContext, MultiThreadExecutor.ResultBu
vmInstance = null;
finalizeEngine();
}

public void multiThreadExecutorExample() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
Context context = Context.create(vmInstance);

context.getGlobalObject().set(context, JavaScriptString.create("print"), JavaScriptJavaCallbackFunctionObject.create(context, "", 1, false, new JavaScriptJavaCallbackFunctionObject.Callback() {
@Override
public Optional<JavaScriptValue> callback(Context context, JavaScriptValue receiverValue, JavaScriptValue[] arguments) {
System.out.println(arguments[0].toString(context).get().toJavaString());
return Optional.empty();
}
}));

MultiThreadExecutor executor = new MultiThreadExecutor(vmInstance);
Bridge.register(context, "HTTP", "get", new Bridge.Adapter() {
@Override
public Optional<JavaScriptValue> callback(Context context, Optional<JavaScriptValue> data) {
String url = "";
if (data.isPresent()) {
Optional<JavaScriptString> mayBeString = data.get().toString(context);
if (mayBeString.isPresent()) {
url = mayBeString.get().toJavaString();
}
}
final String finalURL = url;
MultiThreadExecutor.ExecutorInstance instance = executor.startWorker(context, new MultiThreadExecutor.Executor() {
@Override
public MultiThreadExecutor.ResultBuilderContext run() {
try {
HttpURLConnection connection = (HttpURLConnection)new URL(finalURL).openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { // success
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();

return new MultiThreadExecutor.ResultBuilderContext(true, response.toString());
} else {
return new MultiThreadExecutor.ResultBuilderContext(false, "error HTTP return code:" + responseCode);
}
} catch (IOException e) {
return new MultiThreadExecutor.ResultBuilderContext(false, e.toString());
}
}
}, new MultiThreadExecutor.ResultBuilder() {
@Override
public JavaScriptValue build(Context scriptContext, MultiThreadExecutor.ResultBuilderContext builderContext) {
return JavaScriptString.create((String)builderContext.data());
}
});
return Optional.of(instance.promise());
}
});

Evaluator.evalScript(context, "" +
"let promise1 = HTTP.get('https://httpbin.org/get');" +
"let promise2 = HTTP.get('http://google.com');" +
"Promise.allSettled([promise1, promise2]).then(function(v) {" +
"print(JSON.stringify(v));" +
"print('http all end!');" +
"});", "", false);

while (executor.hasPendingEventOrWorker()) {
executor.pumpEventsFromThreadIfNeeds();
try {
Thread.sleep(25);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

context = null;
vmInstance = null;
finalizeEngine();
}

}

0 comments on commit 5c797fa

Please sign in to comment.