event_machine_flush 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5 -0
- data/ext/event_machine_flush.cpp +106 -1
- data/ext/extconf.rb +4 -3
- data/lib/event_machine_flush/version.rb +9 -1
- metadata +3 -3
data/CHANGELOG
CHANGED
data/ext/event_machine_flush.cpp
CHANGED
@@ -1,11 +1,116 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
#include "project.h"
|
3
3
|
|
4
|
+
|
5
|
+
static void push_back_data(ConnectionDescriptor *ed, char *data, int len) {
|
6
|
+
char *buffer = (char*)malloc(len + 1);
|
7
|
+
if (!buffer)
|
8
|
+
throw std::runtime_error("bad alloc throwing back data");
|
9
|
+
memcpy(buffer, data, len);
|
10
|
+
buffer[len] = 0;
|
11
|
+
ed->OutboundPages.push_front(ConnectionDescriptor::OutboundPage(buffer, len));
|
12
|
+
}
|
13
|
+
|
4
14
|
extern "C" {
|
5
15
|
VALUE EventMachineFlush_flush(VALUE self, VALUE connection) {
|
6
16
|
unsigned long signature = NUM2ULONG(rb_iv_get(connection, "@signature"));
|
7
17
|
ConnectionDescriptor *ed = dynamic_cast<ConnectionDescriptor*>(Bindable_t::GetObject(signature));
|
8
|
-
|
18
|
+
|
19
|
+
// Based on ConnectionDescriptor::_WriteOutboundData.
|
20
|
+
while (ed->OutboundPages.size() > 0) {
|
21
|
+
int sd = ed->GetSocket();
|
22
|
+
|
23
|
+
if (sd == INVALID_SOCKET)
|
24
|
+
break;
|
25
|
+
|
26
|
+
size_t nbytes = 0;
|
27
|
+
#ifdef HAVE_WRITEV
|
28
|
+
int iovcnt = ed->OutboundPages.size();
|
29
|
+
if (iovcnt > 16) iovcnt = 16;
|
30
|
+
|
31
|
+
# ifdef CC_SUNWspro
|
32
|
+
struct iovec iov[16];
|
33
|
+
# else
|
34
|
+
struct iovec iov[iovcnt];
|
35
|
+
# endif
|
36
|
+
|
37
|
+
for(int i = 0; i < iovcnt; i++){
|
38
|
+
ConnectionDescriptor::OutboundPage *op = &(ed->OutboundPages[i]);
|
39
|
+
# ifdef CC_SUNWspro
|
40
|
+
iov[i].iov_base = (char *)(op->Buffer + op->Offset);
|
41
|
+
# else
|
42
|
+
iov[i].iov_base = (void *)(op->Buffer + op->Offset);
|
43
|
+
# endif
|
44
|
+
iov[i].iov_len = op->Length - op->Offset;
|
45
|
+
|
46
|
+
nbytes += iov[i].iov_len;
|
47
|
+
}
|
48
|
+
#else
|
49
|
+
char output_buffer[16 * 1024];
|
50
|
+
|
51
|
+
while ((ed->OutboundPages.size() > 0) && (nbytes < sizeof(output_buffer))) {
|
52
|
+
ConnectionDescriptor::OutboundPage *op = &(OutboundPages[0]);
|
53
|
+
if ((nbytes + op->Length - op->Offset) < sizeof(output_buffer)) {
|
54
|
+
memcpy(output_buffer + nbytes, op->Buffer + op->Offset, op->Length - op->Offset);
|
55
|
+
nbytes += (op->Length - op->Offset);
|
56
|
+
op->Free();
|
57
|
+
ed->OutboundPages.pop_front();
|
58
|
+
} else {
|
59
|
+
int len = sizeof(output_buffer) - nbytes;
|
60
|
+
memcpy(output_buffer + nbytes, op->Buffer + op->Offset, len);
|
61
|
+
op->Offset += len;
|
62
|
+
nbytes += len;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
#endif
|
66
|
+
|
67
|
+
// Noop if only empty pages have been queued.
|
68
|
+
if (nbytes == 0)
|
69
|
+
break;
|
70
|
+
|
71
|
+
#ifdef HAVE_WRITEV
|
72
|
+
int bytes_written = writev(ed->GetSocket(), iov, iovcnt);
|
73
|
+
#else
|
74
|
+
int bytes_written = write(ed->GetSocket(), output_buffer, nbytes);
|
75
|
+
#endif
|
76
|
+
|
77
|
+
// Noop if we couldn't write. Since we didn't select on the
|
78
|
+
// socket, it mightn't be writable.
|
79
|
+
if (bytes_written <= 0) {
|
80
|
+
#ifndef HAVE_WRITEV
|
81
|
+
push_back_data(ed, output_buffer, nbytes);
|
82
|
+
#endif
|
83
|
+
break;
|
84
|
+
}
|
85
|
+
ed->OutboundDataSize -= bytes_written;
|
86
|
+
|
87
|
+
#ifdef HAVE_WRITEV
|
88
|
+
unsigned int sent = bytes_written;
|
89
|
+
deque<ConnectionDescriptor::OutboundPage>::iterator op = ed->OutboundPages.begin();
|
90
|
+
|
91
|
+
for (int i = 0; i < iovcnt; i++) {
|
92
|
+
if (iov[i].iov_len <= sent) {
|
93
|
+
// Sent this page in full, free it.
|
94
|
+
op->Free();
|
95
|
+
ed->OutboundPages.pop_front();
|
96
|
+
|
97
|
+
sent -= iov[i].iov_len;
|
98
|
+
} else {
|
99
|
+
// Sent part (or none) of this page, increment offset to send the remainder
|
100
|
+
op->Offset += sent;
|
101
|
+
break;
|
102
|
+
}
|
103
|
+
|
104
|
+
// Shouldn't be possible run out of pages before the loop ends
|
105
|
+
assert(op != ed->OutboundPages.end());
|
106
|
+
*op++;
|
107
|
+
}
|
108
|
+
#else
|
109
|
+
if ((size_t)bytes_written < nbytes)
|
110
|
+
push_back_data(ed, output_buffer + bytes_written, nbytes - bytes_written);
|
111
|
+
#endif
|
112
|
+
}
|
113
|
+
|
9
114
|
return Qnil;
|
10
115
|
}
|
11
116
|
|
data/ext/extconf.rb
CHANGED
@@ -5,16 +5,17 @@ require 'rubygems'
|
|
5
5
|
specs = Gem.source_index.find_name('eventmachine')
|
6
6
|
specs.size > 0 or
|
7
7
|
abort "can't find eventmachine gem"
|
8
|
-
|
8
|
+
event_machine_path = specs.first.full_gem_path
|
9
9
|
|
10
10
|
# Stub out create_makefile and load EventMachine's extconf.rb. This
|
11
11
|
# ensures our build environment matches.
|
12
12
|
require 'mkmf'
|
13
13
|
alias original_create_makefile create_makefile
|
14
14
|
def create_makefile(*) end
|
15
|
-
require "
|
15
|
+
require "#{event_machine_path}/ext/extconf.rb"
|
16
16
|
alias create_makefile original_create_makefile
|
17
17
|
|
18
18
|
# Create our makefile.
|
19
|
-
$
|
19
|
+
$CPPFLAGS << " -Dprivate=public -Dprotected=public"
|
20
|
+
$INCFLAGS << " -I#{event_machine_path}/ext"
|
20
21
|
create_makefile "event_machine_flush_ext"
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- George Ogata
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-26 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|