Skip to content
This repository was archived by the owner on Oct 19, 2019. It is now read-only.

Commit 0298d9d

Browse files
committed
Don't pass go pointers to C
For go 1.6. Fixes #31.
1 parent a2fb65d commit 0298d9d

File tree

4 files changed

+55
-29
lines changed

4 files changed

+55
-29
lines changed

Makefile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
version?=4.3.59
22
target?=native # available: x64.debug, ia32.debug, ia32.release, x64.release
33

4+
test: v8worker.test
5+
./v8worker.test
6+
47
v8.pc: v8
58
target=$(target) ./build.sh
69

710
v8:
811
fetch --nohooks v8
912
cd v8 && git checkout $(version) && gclient sync
1013

11-
test: v8worker.test
12-
./v8worker.test
13-
14-
1514
v8worker.test: v8.pc *.go *.cc *.h
1615
go test -c
1716

binding.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ using namespace v8;
1111

1212
struct worker_s {
1313
int x;
14-
void* data;
14+
int table_index;
1515
worker_recv_cb cb;
1616
worker_recv_sync_cb sync_cb;
1717
Isolate* isolate;
@@ -100,12 +100,12 @@ std::string ExceptionString(Isolate* isolate, TryCatch* try_catch) {
100100
extern "C" {
101101
#include "_cgo_export.h"
102102

103-
void go_recv_cb(const char* msg, void* data) {
104-
recvCb((char*)msg, data);
103+
void go_recv_cb(const char* msg, int table_index) {
104+
recvCb((char*)msg, table_index);
105105
}
106106

107-
const char* go_recv_sync_cb(const char* msg, void* data) {
108-
return recvSyncCb((char*)msg, data);
107+
const char* go_recv_sync_cb(const char* msg, int table_index) {
108+
return recvSyncCb((char*)msg, table_index);
109109
}
110110

111111
const char* worker_version() {
@@ -225,7 +225,7 @@ void Send(const FunctionCallbackInfo<Value>& args) {
225225
}
226226

227227
// XXX should we use Unlocker?
228-
w->cb(msg.c_str(), w->data);
228+
w->cb(msg.c_str(), w->table_index);
229229
}
230230

231231
// Called from javascript using $request.
@@ -250,7 +250,7 @@ void SendSync(const FunctionCallbackInfo<Value>& args) {
250250
String::Utf8Value str(v);
251251
msg = ToCString(str);
252252
}
253-
const char* returnMsg = w->sync_cb(msg.c_str(), w->data);
253+
const char* returnMsg = w->sync_cb(msg.c_str(), w->table_index);
254254
Local<String> returnV = String::NewFromUtf8(w->isolate, returnMsg);
255255
args.GetReturnValue().Set(returnV);
256256
}
@@ -329,7 +329,7 @@ void v8_init() {
329329
V8::SetArrayBufferAllocator(&array_buffer_allocator);
330330
}
331331

332-
worker* worker_new(worker_recv_cb cb, worker_recv_sync_cb sync_cb, void* data) {
332+
worker* worker_new(worker_recv_cb cb, worker_recv_sync_cb sync_cb, int table_index) {
333333
Isolate* isolate = Isolate::New();
334334
Locker locker(isolate);
335335
Isolate::Scope isolate_scope(isolate);
@@ -339,7 +339,7 @@ worker* worker_new(worker_recv_cb cb, worker_recv_sync_cb sync_cb, void* data) {
339339
w->isolate = isolate;
340340
w->isolate->SetCaptureStackTraceForUncaughtExceptions(true);
341341
w->isolate->SetData(0, w);
342-
w->data = data;
342+
w->table_index = table_index;
343343
w->cb = cb;
344344
w->sync_cb = sync_cb;
345345

binding.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ extern "C" {
33
#endif
44

55

6-
void go_recv_cb(const char* msg, void* data);
7-
const char* go_recv_sync_cb(const char* msg, void* data);
6+
void go_recv_cb(const char* msg, int table_index);
7+
const char* go_recv_sync_cb(const char* msg, int table_index);
88

99
struct worker_s;
1010
typedef struct worker_s worker;
11-
typedef void (*worker_recv_cb)(const char* msg, void* data);
12-
typedef const char* (*worker_recv_sync_cb)(const char* msg, void* data);
11+
typedef void (*worker_recv_cb)(const char* msg, int table_index);
12+
typedef const char* (*worker_recv_sync_cb)(const char* msg, int table_index);
1313

1414
const char* worker_version();
1515

1616
void v8_init();
1717

18-
worker* worker_new(worker_recv_cb cb, worker_recv_sync_cb sync_cb, void* data);
18+
worker* worker_new(worker_recv_cb cb, worker_recv_sync_cb sync_cb, int table_index);
1919

2020
// returns nonzero on error
2121
// get error from worker_last_exception

worker.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ import "unsafe"
1313
import "sync"
1414
import "runtime"
1515

16+
type workerTableIndex int
17+
18+
var workerTableLock sync.Mutex
19+
20+
// This table will store all pointers to all active workers. Because we can't safely
21+
// pass pointers to Go objects to C, we instead pass a key to this table.
22+
var workerTable = make(map[workerTableIndex]*Worker)
23+
24+
// Keeps track of the last used table index. Incremeneted when a worker is created.
25+
var workerTableNextAvailable workerTableIndex = 0
26+
1627
// To receive messages from javascript...
1728
type ReceiveMessageCallback func(msg string)
1829

@@ -27,49 +38,65 @@ var initV8Once sync.Once
2738

2839
// This is a golang wrapper around a single V8 Isolate.
2940
type Worker struct {
30-
cWorker *C.worker
31-
cb ReceiveMessageCallback
32-
sync_cb ReceiveSyncMessageCallback
41+
cWorker *C.worker
42+
cb ReceiveMessageCallback
43+
sync_cb ReceiveSyncMessageCallback
44+
tableIndex workerTableIndex
3345
}
3446

3547
// Return the V8 version E.G. "4.3.59"
3648
func Version() string {
3749
return C.GoString(C.worker_version())
3850
}
3951

52+
func workerTableLookup(index workerTableIndex) *Worker {
53+
workerTableLock.Lock()
54+
defer workerTableLock.Unlock()
55+
return workerTable[index]
56+
}
57+
4058
//export recvCb
41-
func recvCb(msg_s *C.char, ptr unsafe.Pointer) {
59+
func recvCb(msg_s *C.char, index workerTableIndex) {
4260
msg := C.GoString(msg_s)
43-
worker := (*Worker)(ptr)
61+
worker := workerTableLookup(index)
4462
worker.cb(msg)
4563
}
4664

4765
//export recvSyncCb
48-
func recvSyncCb(msg_s *C.char, ptr unsafe.Pointer) *C.char {
66+
func recvSyncCb(msg_s *C.char, index workerTableIndex) *C.char {
4967
msg := C.GoString(msg_s)
50-
worker := (*Worker)(ptr)
68+
worker := workerTableLookup(index)
5169
return_s := C.CString(worker.sync_cb(msg))
5270
return return_s
5371
}
5472

5573
// Creates a new worker, which corresponds to a V8 isolate. A single threaded
5674
// standalone execution context.
5775
func New(cb ReceiveMessageCallback, sync_cb ReceiveSyncMessageCallback) *Worker {
76+
workerTableLock.Lock()
5877
worker := &Worker{
59-
cb: cb,
60-
sync_cb: sync_cb,
78+
cb: cb,
79+
sync_cb: sync_cb,
80+
tableIndex: workerTableNextAvailable,
6181
}
6282

83+
workerTableNextAvailable++
84+
workerTable[worker.tableIndex] = worker
85+
workerTableLock.Unlock()
86+
6387
initV8Once.Do(func() {
6488
C.v8_init()
6589
})
6690

6791
callback := C.worker_recv_cb(C.go_recv_cb)
6892
receiveSync_callback := C.worker_recv_sync_cb(C.go_recv_sync_cb)
6993

70-
worker.cWorker = C.worker_new(callback, receiveSync_callback, unsafe.Pointer(worker))
94+
worker.cWorker = C.worker_new(callback, receiveSync_callback, C.int(worker.tableIndex))
7195
runtime.SetFinalizer(worker, func(final_worker *Worker) {
72-
C.worker_dispose(final_worker.cWorker) // Delete this worker on finalize (GC)
96+
workerTableLock.Lock()
97+
delete(workerTable, final_worker.tableIndex)
98+
workerTableLock.Unlock()
99+
C.worker_dispose(final_worker.cWorker)
73100
})
74101
return worker
75102
}

0 commit comments

Comments
 (0)