Go: removing request registry.
Passing unsafe.Pointers (void *) from Go to C is complicated by an attempt to make such pointers less unsafe. A straightforward optimization is to replace 'unsafe.Pointer' with 'uintptr' (thanks to Xin Huang for the idea: https://stackoverflow.com/a/44826533 ). As a result, request registry with mutex is gone.
This commit is contained in:
@@ -13,7 +13,7 @@ import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type request struct {
|
||||
@@ -21,28 +21,14 @@ type request struct {
|
||||
resp *response
|
||||
c_req C.nxt_go_request_t
|
||||
id C.uint32_t
|
||||
msgs []*cmsg
|
||||
ch chan *cmsg
|
||||
}
|
||||
|
||||
func (r *request) Read(p []byte) (n int, err error) {
|
||||
c := C.size_t(cap(p))
|
||||
b := C.malloc(c)
|
||||
b := C.uintptr_t(uintptr(unsafe.Pointer(&p[0])))
|
||||
|
||||
res := C.nxt_go_request_read(r.c_req, b, c)
|
||||
|
||||
if res == -2 /* NXT_AGAIN */ {
|
||||
m := <-r.ch
|
||||
|
||||
res = C.nxt_go_request_read_from(r.c_req, b, c, m.buf.b,
|
||||
m.buf.s)
|
||||
r.push(m)
|
||||
}
|
||||
|
||||
if res > 0 {
|
||||
copy(p, C.GoBytes(b, res))
|
||||
}
|
||||
|
||||
C.free(b)
|
||||
return int(res), nil
|
||||
}
|
||||
|
||||
@@ -51,53 +37,6 @@ func (r *request) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type request_registry struct {
|
||||
sync.RWMutex
|
||||
m map[C.nxt_go_request_t]*request
|
||||
id map[C.uint32_t]*request
|
||||
}
|
||||
|
||||
var request_registry_ request_registry
|
||||
|
||||
func find_request(c_req C.nxt_go_request_t) *request {
|
||||
request_registry_.RLock()
|
||||
res := request_registry_.m[c_req]
|
||||
request_registry_.RUnlock()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func find_request_by_id(id C.uint32_t) *request {
|
||||
request_registry_.RLock()
|
||||
res := request_registry_.id[id]
|
||||
request_registry_.RUnlock()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func add_request(r *request) {
|
||||
request_registry_.Lock()
|
||||
if request_registry_.m == nil {
|
||||
request_registry_.m = make(map[C.nxt_go_request_t]*request)
|
||||
request_registry_.id = make(map[C.uint32_t]*request)
|
||||
}
|
||||
|
||||
request_registry_.m[r.c_req] = r
|
||||
request_registry_.id[r.id] = r
|
||||
|
||||
request_registry_.Unlock()
|
||||
}
|
||||
|
||||
func remove_request(r *request) {
|
||||
request_registry_.Lock()
|
||||
if request_registry_.m != nil {
|
||||
delete(request_registry_.m, r.c_req)
|
||||
delete(request_registry_.id, r.id)
|
||||
}
|
||||
|
||||
request_registry_.Unlock()
|
||||
}
|
||||
|
||||
func (r *request) response() *response {
|
||||
if r.resp == nil {
|
||||
r.resp = new_response(r.c_req, &r.req)
|
||||
@@ -107,33 +46,23 @@ func (r *request) response() *response {
|
||||
}
|
||||
|
||||
func (r *request) done() {
|
||||
remove_request(r)
|
||||
|
||||
C.nxt_go_request_done(r.c_req)
|
||||
|
||||
for _, m := range r.msgs {
|
||||
m.Close()
|
||||
}
|
||||
|
||||
if r.ch != nil {
|
||||
close(r.ch)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) push(m *cmsg) {
|
||||
r.msgs = append(r.msgs, m)
|
||||
func get_request(go_req C.nxt_go_request_t) *request {
|
||||
return (*request)(unsafe.Pointer(uintptr(go_req)))
|
||||
}
|
||||
|
||||
//export nxt_go_new_request
|
||||
func nxt_go_new_request(c_req C.nxt_go_request_t, id C.uint32_t,
|
||||
c_method *C.nxt_go_str_t, c_uri *C.nxt_go_str_t) {
|
||||
c_method *C.nxt_go_str_t, c_uri *C.nxt_go_str_t) uintptr {
|
||||
|
||||
uri := C.GoStringN(c_uri.start, c_uri.length)
|
||||
|
||||
var URL *url.URL
|
||||
var err error
|
||||
if URL, err = url.ParseRequestURI(uri); err != nil {
|
||||
return
|
||||
return 0
|
||||
}
|
||||
|
||||
r := &request{
|
||||
@@ -146,76 +75,49 @@ func nxt_go_new_request(c_req C.nxt_go_request_t, id C.uint32_t,
|
||||
},
|
||||
c_req: c_req,
|
||||
id: id,
|
||||
msgs: make([]*cmsg, 0, 1),
|
||||
}
|
||||
r.req.Body = r
|
||||
|
||||
add_request(r)
|
||||
}
|
||||
|
||||
//export nxt_go_find_request
|
||||
func nxt_go_find_request(id C.uint32_t) C.nxt_go_request_t {
|
||||
r := find_request_by_id(id)
|
||||
|
||||
if r != nil {
|
||||
return r.c_req
|
||||
}
|
||||
|
||||
return 0
|
||||
return uintptr(unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
//export nxt_go_request_set_proto
|
||||
func nxt_go_request_set_proto(c_req C.nxt_go_request_t, proto *C.nxt_go_str_t,
|
||||
func nxt_go_request_set_proto(go_req C.nxt_go_request_t, proto *C.nxt_go_str_t,
|
||||
maj C.int, min C.int) {
|
||||
|
||||
r := find_request(c_req)
|
||||
r := get_request(go_req)
|
||||
r.req.Proto = C.GoStringN(proto.start, proto.length)
|
||||
r.req.ProtoMajor = int(maj)
|
||||
r.req.ProtoMinor = int(min)
|
||||
}
|
||||
|
||||
//export nxt_go_request_add_header
|
||||
func nxt_go_request_add_header(c_req C.nxt_go_request_t, name *C.nxt_go_str_t,
|
||||
func nxt_go_request_add_header(go_req C.nxt_go_request_t, name *C.nxt_go_str_t,
|
||||
value *C.nxt_go_str_t) {
|
||||
|
||||
r := find_request(c_req)
|
||||
r := get_request(go_req)
|
||||
r.req.Header.Add(C.GoStringN(name.start, name.length),
|
||||
C.GoStringN(value.start, value.length))
|
||||
}
|
||||
|
||||
//export nxt_go_request_set_content_length
|
||||
func nxt_go_request_set_content_length(c_req C.nxt_go_request_t, l C.int64_t) {
|
||||
find_request(c_req).req.ContentLength = int64(l)
|
||||
}
|
||||
|
||||
//export nxt_go_request_create_channel
|
||||
func nxt_go_request_create_channel(c_req C.nxt_go_request_t) {
|
||||
find_request(c_req).ch = make(chan *cmsg)
|
||||
func nxt_go_request_set_content_length(go_req C.nxt_go_request_t, l C.int64_t) {
|
||||
get_request(go_req).req.ContentLength = int64(l)
|
||||
}
|
||||
|
||||
//export nxt_go_request_set_host
|
||||
func nxt_go_request_set_host(c_req C.nxt_go_request_t, host *C.nxt_go_str_t) {
|
||||
find_request(c_req).req.Host = C.GoStringN(host.start, host.length)
|
||||
func nxt_go_request_set_host(go_req C.nxt_go_request_t, host *C.nxt_go_str_t) {
|
||||
get_request(go_req).req.Host = C.GoStringN(host.start, host.length)
|
||||
}
|
||||
|
||||
//export nxt_go_request_set_url
|
||||
func nxt_go_request_set_url(c_req C.nxt_go_request_t, scheme *C.char) {
|
||||
find_request(c_req).req.URL.Scheme = C.GoString(scheme)
|
||||
func nxt_go_request_set_url(go_req C.nxt_go_request_t, scheme *C.char) {
|
||||
get_request(go_req).req.URL.Scheme = C.GoString(scheme)
|
||||
}
|
||||
|
||||
//export nxt_go_request_set_remote_addr
|
||||
func nxt_go_request_set_remote_addr(c_req C.nxt_go_request_t,
|
||||
func nxt_go_request_set_remote_addr(go_req C.nxt_go_request_t,
|
||||
addr *C.nxt_go_str_t) {
|
||||
|
||||
find_request(c_req).req.RemoteAddr = C.GoStringN(addr.start, addr.length)
|
||||
}
|
||||
|
||||
//export nxt_go_request_serve
|
||||
func nxt_go_request_serve(c_req C.nxt_go_request_t) {
|
||||
r := find_request(c_req)
|
||||
|
||||
go func(r *request) {
|
||||
http.DefaultServeMux.ServeHTTP(r.response(), &r.req)
|
||||
r.done()
|
||||
}(r)
|
||||
get_request(go_req).req.RemoteAddr = C.GoStringN(addr.start, addr.length)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user