Skip to content

Commit

Permalink
Merge pull request #1349 from exokitxr/threadpool
Browse files Browse the repository at this point in the history
Thread pool for native bindings
  • Loading branch information
Avaer Kazmer committed Jul 31, 2019
2 parents 8c518b0 + 654fa7c commit 1f95e1f
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 56 deletions.
12 changes: 12 additions & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'deps/exokit-bindings/util/src/*.cc',
'deps/exokit-bindings/console/src/*.cc',
'deps/exokit-bindings/cache/src/*.cc',
'deps/exokit-bindings/threadpool/src/*.cc',
'deps/exokit-bindings/browser/src/*.cpp',
'deps/exokit-bindings/canvas/src/*.cpp',
'deps/exokit-bindings/nanosvg/src/*.cpp',
Expand Down Expand Up @@ -49,6 +50,7 @@
'<(module_root_dir)/deps/exokit-bindings/util/include',
'<(module_root_dir)/deps/exokit-bindings/console/include',
'<(module_root_dir)/deps/exokit-bindings/cache/include',
'<(module_root_dir)/deps/exokit-bindings/threadpool/include',
'<(module_root_dir)/deps/exokit-bindings/bindings/include',
'<(module_root_dir)/deps/exokit-bindings/canvas/include',
'<(module_root_dir)/deps/exokit-bindings/browser/include',
Expand Down Expand Up @@ -135,6 +137,7 @@
'<!@(ls -1 deps/exokit-bindings/util/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/console/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/cache/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/threadpool/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/browser/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/canvas/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/nanosvg/src/*.cpp)',
Expand Down Expand Up @@ -167,6 +170,7 @@
'<(module_root_dir)/deps/exokit-bindings/util/include',
'<(module_root_dir)/deps/exokit-bindings/console/include',
'<(module_root_dir)/deps/exokit-bindings/cache/include',
'<(module_root_dir)/deps/exokit-bindings/threadpool/include',
'<(module_root_dir)/deps/exokit-bindings/bindings/include',
'<(module_root_dir)/deps/exokit-bindings/canvas/include',
'<(module_root_dir)/deps/exokit-bindings/browser/include',
Expand Down Expand Up @@ -249,6 +253,7 @@
'<!@(ls -1 deps/exokit-bindings/util/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/console/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/cache/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/threadpool/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/canvas/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/nanosvg/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/canvascontext/src/*.cc)',
Expand Down Expand Up @@ -276,6 +281,7 @@
'<(module_root_dir)/deps/exokit-bindings/util/include',
'<(module_root_dir)/deps/exokit-bindings/console/include',
'<(module_root_dir)/deps/exokit-bindings/cache/include',
'<(module_root_dir)/deps/exokit-bindings/threadpool/include',
'<(module_root_dir)/deps/exokit-bindings/bindings/include',
'<(module_root_dir)/deps/exokit-bindings/canvas/include',
'<(module_root_dir)/deps/exokit-bindings/nanosvg/include',
Expand Down Expand Up @@ -352,6 +358,7 @@
'<!@(ls -1 deps/exokit-bindings/util/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/console/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/cache/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/threadpool/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/browser/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/canvas/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/nanosvg/src/*.cpp)',
Expand Down Expand Up @@ -384,6 +391,7 @@
'<(module_root_dir)/deps/exokit-bindings/util/include',
'<(module_root_dir)/deps/exokit-bindings/console/include',
'<(module_root_dir)/deps/exokit-bindings/cache/include',
'<(module_root_dir)/deps/exokit-bindings/threadpool/include',
'<(module_root_dir)/deps/exokit-bindings/bindings/include',
'<(module_root_dir)/deps/exokit-bindings/canvas/include',
'<(module_root_dir)/deps/exokit-bindings/browser/include',
Expand Down Expand Up @@ -467,6 +475,7 @@
'<!@(ls -1 deps/exokit-bindings/util/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/console/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/cache/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/threadpool/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/browser/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/canvas/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/nanosvg/src/*.cpp)',
Expand Down Expand Up @@ -499,6 +508,7 @@
'<(module_root_dir)/deps/exokit-bindings/util/include',
'<(module_root_dir)/deps/exokit-bindings/console/include',
'<(module_root_dir)/deps/exokit-bindings/cache/include',
'<(module_root_dir)/deps/exokit-bindings/threadpool/include',
'<(module_root_dir)/deps/exokit-bindings/bindings/include',
'<(module_root_dir)/deps/exokit-bindings/canvas/include',
'<(module_root_dir)/deps/exokit-bindings/browser/include',
Expand Down Expand Up @@ -558,6 +568,7 @@
'<!@(ls -1 deps/exokit-bindings/util/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/console/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/cache/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/threadpool/src/*.cc)',
'<!@(ls -1 deps/exokit-bindings/browser/src/browser-android.cpp)',
'<!@(ls -1 deps/exokit-bindings/canvas/src/*.cpp)',
'<!@(ls -1 deps/exokit-bindings/nanosvg/src/*.cpp)',
Expand Down Expand Up @@ -599,6 +610,7 @@
'<(module_root_dir)/deps/exokit-bindings/util/include',
'<(module_root_dir)/deps/exokit-bindings/console/include',
'<(module_root_dir)/deps/exokit-bindings/cache/include',
'<(module_root_dir)/deps/exokit-bindings/threadpool/include',
'<(module_root_dir)/deps/exokit-bindings/bindings/include',
'<(module_root_dir)/deps/exokit-bindings/canvas/include',
'<(module_root_dir)/deps/exokit-bindings/browser/include',
Expand Down
10 changes: 5 additions & 5 deletions deps/exokit-bindings/canvascontext/include/image-context.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#ifndef _CANVASCONTEXT_IMAGE_H_
#define _CANVASCONTEXT_IMAGE_H_

#include <string>
#include <thread>

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <defines.h>
#include <canvas/include/Context.h>
#include <canvas/include/Image.h>
Expand All @@ -14,8 +18,7 @@
#include <nanosvg.h>
#include <nanosvgrast.h>
#include <windowsystem.h>
#include <string>
#include <thread>
#include <threadpool.h>

using namespace v8;
using namespace node;
Expand All @@ -27,7 +30,6 @@ class Image : public ObjectWrap {
unsigned int GetHeight();
unsigned int GetNumChannels();
// unsigned char *GetData();
static void RunInMainThread(uv_async_t *handle);
void Load(Local<ArrayBuffer> arrayBuffer, size_t byteOffset, size_t byteLength, Local<Function> cbFn);
// void Set(canvas::Image *image);

Expand All @@ -45,12 +47,10 @@ class Image : public ObjectWrap {
sk_sp<SkImage> image;
Nan::Persistent<Uint8ClampedArray> dataArray;

Nan::Persistent<ArrayBuffer> arrayBuffer;
Nan::Persistent<Function> cbFn;
bool loading;
bool hasCbFn;
std::string error;
uv_async_t threadAsyncHandle;
uv_sem_t sem;

friend class CanvasRenderingContext2D;
Expand Down
75 changes: 32 additions & 43 deletions deps/exokit-bindings/canvascontext/src/image-context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,59 +46,28 @@ unsigned int Image::GetNumChannels() {
}
} */

void Image::RunInMainThread(uv_async_t *handle) {
Nan::HandleScope scope;

Image *image = (Image *)handle->data;

Local<Object> asyncObject = Nan::New<Object>();
AsyncResource asyncResource(Isolate::GetCurrent(), asyncObject, "Image::RunInMainThread");

Local<Function> cbFn = Nan::New(image->cbFn);
Local<String> arg0 = Nan::New<String>(image->error).ToLocalChecked();
Local<Value> argv[] = {
arg0,
};
asyncResource.MakeCallback(cbFn, sizeof(argv)/sizeof(argv[0]), argv);

image->cbFn.Reset();
image->arrayBuffer.Reset();
image->error = "";

uv_close((uv_handle_t *)handle, nullptr);
}

void Image::Load(Local<ArrayBuffer> arrayBuffer, size_t byteOffset, size_t byteLength, Local<Function> cbFn) {
if (!this->loading) {
unsigned char *buffer = (unsigned char *)arrayBuffer->GetContents().Data() + byteOffset;
sk_sp<SkData> extendedData = SkData::MakeUninitialized(byteLength + 1);
memcpy((unsigned char *)extendedData->data(), buffer, byteLength);
sk_sp<SkData> data = SkData::MakeWithoutCopy(buffer, byteLength);

this->arrayBuffer.Reset(arrayBuffer);
this->cbFn.Reset(cbFn);
this->loading = true;
this->hasCbFn = !cbFn.IsEmpty();

if (this->hasCbFn) {
uv_loop_t *loop = windowsystembase::GetEventLoop();
uv_async_init(loop, &this->threadAsyncHandle, RunInMainThread);
this->threadAsyncHandle.data = this;
} else {
uv_sem_init(&this->sem, 0);
}

std::thread([this, buffer, byteLength]() -> void {
sk_sp<SkData> data = SkData::MakeWithoutCopy(buffer, byteLength);

auto loadFn = [this, extendedData, data]() -> void {
SkBitmap bitmap;
bool ok = DecodeDataToBitmap(data, &bitmap);

if (ok) {
bitmap.setImmutable();
this->image = SkImage::MakeFromBitmap(bitmap);
} else {
unique_ptr<char[]> svgString(new char[byteLength + 1]);
memcpy(svgString.get(), buffer, byteLength);
svgString[byteLength] = 0;
((char *)extendedData->data())[extendedData->size() - 1] = 0; // NUL-terminate

NSVGimage *svgImage = nsvgParse(svgString.get(), "px", 96);
NSVGimage *svgImage = nsvgParse((char *)extendedData->data(), "px", 96);
if (svgImage != nullptr) {
if (svgImage->width > 0 && svgImage->height > 0 && svgImage->shapes != nullptr) {
int w = svgImage->width;
Expand Down Expand Up @@ -134,14 +103,34 @@ void Image::Load(Local<ArrayBuffer> arrayBuffer, size_t byteOffset, size_t byteL
}
}

if (this->hasCbFn) {
uv_async_send(&this->threadAsyncHandle);
} else {
if (!this->hasCbFn) {
uv_sem_post(&this->sem);
}
}).detach();
};

if (this->hasCbFn) {
threadpool::ThreadPool *threadPool = threadpool::getWindowThreadPool();
threadPool->queueWork(loadFn, [this]() -> void {
Nan::HandleScope scope;

Local<Object> asyncObject = Nan::New<Object>();
AsyncResource asyncResource(Isolate::GetCurrent(), asyncObject, "Image::Load");

Local<Function> cbFn = Nan::New(this->cbFn);
Local<String> arg0 = Nan::New<String>(this->error).ToLocalChecked();
Local<Value> argv[] = {
arg0,
};
asyncResource.MakeCallback(cbFn, sizeof(argv)/sizeof(argv[0]), argv);

this->cbFn.Reset();
this->error = "";
});
} else {
uv_sem_init(&this->sem, 0);

loadFn();

if (!this->hasCbFn) {
uv_sem_wait(&this->sem);
uv_sem_destroy(&this->sem);

Expand Down
52 changes: 52 additions & 0 deletions deps/exokit-bindings/threadpool/include/threadpool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef _THREADPOOL_H_
#define _THREADPOOL_H_

#include <thread>
#include <mutex>
#include <functional>

#include <v8.h>
#include <nan.h>

#include <windowsystem.h>

using namespace v8;

#define NUM_THREADS 8

namespace threadpool {

class QueueEntry {
public:
QueueEntry(std::function<void()> workFn, std::function<void()> cbFn);
QueueEntry();

std::function<void()> workFn;
std::function<void()> cbFn;
};

class ThreadPool {
public:
ThreadPool();
~ThreadPool();

void queueWork(std::function<void()> workFn = []() -> void {}, std::function<void()> cbFn = []() -> void {});
static void asyncFn(uv_async_t *handle);

// protected:
std::vector<std::thread *> threads;
std::deque<QueueEntry> reqQueue;
std::deque<std::function<void()>> resQueue;
uv_async_t *asyncHandle;
std::mutex mutex;
uv_sem_t sem;
bool live;
};

extern thread_local ThreadPool *windowThreadPool;
ThreadPool *getWindowThreadPool();
void destroyWindowThreadPool();

};

#endif
Loading

0 comments on commit 1f95e1f

Please sign in to comment.