WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit df77aaa

Browse files
Move code around
1 parent bdf3182 commit df77aaa

File tree

4 files changed

+110
-102
lines changed

4 files changed

+110
-102
lines changed

ext/hyper_ruby/src/gvl_helpers.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::{ffi::c_void, mem::MaybeUninit, ptr::null_mut};
2+
use rb_sys::rb_thread_call_without_gvl;
3+
4+
// Call a specified function, having released the GVL. Acquires the GVL before returning.
5+
pub(crate) fn nogvl<F, R>(mut func: F) -> R
6+
where
7+
F: FnMut() -> R,
8+
R: Sized,
9+
{
10+
unsafe extern "C" fn call_without_gvl<F, R>(arg: *mut c_void) -> *mut c_void
11+
where
12+
F: FnMut() -> R,
13+
R: Sized,
14+
{
15+
let arg = arg as *mut (&mut F, &mut MaybeUninit<R>);
16+
let (func, result) = unsafe { &mut *arg };
17+
result.write(func());
18+
null_mut()
19+
}
20+
let result = MaybeUninit::uninit();
21+
let arg_ptr = &(&mut func, &result) as *const _ as *mut c_void;
22+
unsafe {
23+
rb_thread_call_without_gvl(Some(call_without_gvl::<F, R>), arg_ptr, None, null_mut());
24+
result.assume_init()
25+
}
26+
}

ext/hyper_ruby/src/lib.rs

Lines changed: 10 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
mod request;
2+
mod response;
3+
mod gvl_helpers;
4+
5+
use request::Request;
6+
use response::Response;
7+
use gvl_helpers::nogvl;
8+
19
use magnus::block::block_proc;
210
use magnus::r_hash::ForEach;
311
use magnus::typed_data::Obj;
4-
use magnus::value::{qnil, Opaque};
5-
use magnus::{function, gc, method, prelude::*, DataTypeFunctions, Error as MagnusError, RString, Ruby, TypedData, Value};
12+
use magnus::{function, method, prelude::*, Error as MagnusError, Ruby, Value};
613
use bytes::Bytes;
714

8-
use std::{ffi::c_void, mem::MaybeUninit, ptr::null_mut};
9-
10-
use rb_sys::rb_thread_call_without_gvl;
11-
1215
use warp::Filter;
1316
use warp::http::Response as WarpResponse;
1417
use std::cell::RefCell;
@@ -35,84 +38,13 @@ impl ServerConfig {
3538
}
3639
}
3740

41+
// Sent on the work channel with the request, and a oneshot channel to send the response back on.
3842
struct RequestWithCompletion {
3943
request: Request,
4044
// sent a response back on this thread
4145
response_tx: oneshot::Sender<WarpResponse<Bytes>>,
4246
}
4347

44-
// Request type that will be sent to worker threads
45-
#[derive(Debug)]
46-
#[magnus::wrap(class = "HyperRuby::Request")]
47-
struct Request {
48-
method: warp::http::Method,
49-
path: String,
50-
headers: warp::http::HeaderMap,
51-
body: Bytes,
52-
}
53-
54-
impl Request {
55-
pub fn method(&self) -> String {
56-
self.method.to_string()
57-
}
58-
59-
pub fn path(&self) -> RString {
60-
RString::new(&self.path)
61-
}
62-
63-
pub fn header(&self, key: String) -> Value {
64-
match self.headers.get(key) {
65-
Some(value) => match value.to_str() {
66-
Ok(value) => RString::new(value).as_value(),
67-
Err(_) => qnil().as_value(),
68-
},
69-
None => qnil().as_value(),
70-
}
71-
}
72-
73-
pub fn body_size(&self) -> usize {
74-
self.body.len()
75-
}
76-
77-
pub fn body(&self) -> Value {
78-
if self.body.is_empty() {
79-
return qnil().as_value();
80-
}
81-
82-
let result = RString::buf_new(self.body_size());
83-
84-
// cat to the end of the string directly from the byte buffer
85-
result.cat(self.body.as_ref());
86-
result.as_value()
87-
}
88-
}
89-
90-
91-
#[derive(TypedData)]
92-
#[magnus(class = "HyperRuby::Response", mark)]
93-
struct Response {
94-
status: u16,
95-
headers: Opaque<magnus::RHash>,
96-
body: Opaque<magnus::RString>,
97-
}
98-
99-
impl DataTypeFunctions for Response {
100-
fn mark(&self, marker: &gc::Marker) {
101-
marker.mark(self.headers);
102-
marker.mark(self.body);
103-
}
104-
}
105-
106-
impl Response {
107-
pub fn new(status: u16, headers: magnus::RHash, body: RString) -> Self {
108-
Self {
109-
status,
110-
headers: headers.into(),
111-
body: body.into(),
112-
}
113-
}
114-
}
115-
11648
#[magnus::wrap(class = "HyperRuby::Server")]
11749
struct Server {
11850
server_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
@@ -121,30 +53,6 @@ struct Server {
12153
work_tx: RefCell<Option<Arc<crossbeam_channel::Sender<RequestWithCompletion>>>>,
12254
}
12355

124-
125-
pub(crate) fn nogvl<F, R>(mut func: F) -> R
126-
where
127-
F: FnMut() -> R,
128-
R: Sized,
129-
{
130-
unsafe extern "C" fn call_without_gvl<F, R>(arg: *mut c_void) -> *mut c_void
131-
where
132-
F: FnMut() -> R,
133-
R: Sized,
134-
{
135-
let arg = arg as *mut (&mut F, &mut MaybeUninit<R>);
136-
let (func, result) = unsafe { &mut *arg };
137-
result.write(func());
138-
null_mut()
139-
}
140-
let result = MaybeUninit::uninit();
141-
let arg_ptr = &(&mut func, &result) as *const _ as *mut c_void;
142-
unsafe {
143-
rb_thread_call_without_gvl(Some(call_without_gvl::<F, R>), arg_ptr, None, null_mut());
144-
result.assume_init()
145-
}
146-
}
147-
14856
impl Server {
14957
pub fn new() -> Self {
15058
let (work_tx, work_rx) = crossbeam_channel::bounded(1000);

ext/hyper_ruby/src/request.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use magnus::{value::{qnil, ReprValue}, RString, Value};
2+
use bytes::Bytes;
3+
use warp::http::HeaderMap;
4+
5+
// Type passed to ruby giving access to the request properties.
6+
#[derive(Debug)]
7+
#[magnus::wrap(class = "HyperRuby::Request")]
8+
pub struct Request {
9+
pub method: warp::http::Method,
10+
pub path: String,
11+
pub headers: HeaderMap,
12+
pub body: Bytes,
13+
}
14+
15+
impl Request {
16+
pub fn method(&self) -> String {
17+
self.method.to_string()
18+
}
19+
20+
pub fn path(&self) -> RString {
21+
RString::new(&self.path)
22+
}
23+
24+
pub fn header(&self, key: String) -> Value {
25+
match self.headers.get(key) {
26+
Some(value) => match value.to_str() {
27+
Ok(value) => RString::new(value).as_value(),
28+
Err(_) => qnil().as_value(),
29+
},
30+
None => qnil().as_value(),
31+
}
32+
}
33+
34+
pub fn body_size(&self) -> usize {
35+
self.body.len()
36+
}
37+
38+
pub fn body(&self) -> Value {
39+
if self.body.is_empty() {
40+
return qnil().as_value();
41+
}
42+
43+
let result = RString::buf_new(self.body_size());
44+
result.cat(self.body.as_ref());
45+
result.as_value()
46+
}
47+
}

ext/hyper_ruby/src/response.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use magnus::{gc, DataTypeFunctions, RHash, RString, TypedData, value::Opaque};
2+
3+
// Response object returned to Ruby; holds reference to the opaque ruby types for the headers and body.
4+
#[derive(TypedData)]
5+
#[magnus(class = "HyperRuby::Response", mark)]
6+
pub struct Response {
7+
pub status: u16,
8+
pub headers: Opaque<RHash>,
9+
pub body: Opaque<RString>,
10+
}
11+
12+
impl DataTypeFunctions for Response {
13+
fn mark(&self, marker: &gc::Marker) {
14+
marker.mark(self.headers);
15+
marker.mark(self.body);
16+
}
17+
}
18+
19+
impl Response {
20+
pub fn new(status: u16, headers: RHash, body: RString) -> Self {
21+
Self {
22+
status,
23+
headers: headers.into(),
24+
body: body.into(),
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)