Permalink
Browse files

add a new code path to avoid unneccessary memcpy

  • Loading branch information...
1 parent 98cc29d commit 9b15eb6973dd30fb2287ee3fa44cb0a7ec6c6428 @jakedouglas jakedouglas committed Nov 4, 2009
Showing with 32 additions and 8 deletions.
  1. +12 −0 ext/cmain.cpp
  2. +15 −0 ext/ed.cpp
  3. +1 −0 ext/ed.h
  4. +1 −0 ext/eventmachine.h
  5. +3 −8 ext/rubymain.cpp
View
@@ -353,6 +353,18 @@ extern "C" int evma_send_datagram (const unsigned long binding, const char *data
return DatagramDescriptor::SendDatagram (binding, data, data_length, address, port);
}
+/*************************
+evma_send_without_copying
+*************************/
+
+extern "C" int evma_send_without_copying (const unsigned long binding, const char *data, int data_length)
+{
+ ensure_eventmachine("evma_send_without_copying");
+ ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
+ if (cd)
+ return cd->SendWithoutCopying(data, data_length);
+ return -1;
+}
/*********************
evma_close_connection
View
@@ -521,6 +521,21 @@ int ConnectionDescriptor::SendOutboundData (const char *data, int length)
}
+int ConnectionDescriptor::SendWithoutCopying(const char *data, int length)
+{
+ if (IsCloseScheduled())
+ return 0;
+
+ if (!data && (length > 0))
+ throw std::runtime_error ("bad outbound data");
+
+ OutboundPages.push_back (OutboundPage (data, length));
+ OutboundDataSize += length;
+
+ _UpdateEvents(false, true);
+
+ return length;
+}
/******************************************
ConnectionDescriptor::_SendRawOutboundData
View
@@ -154,6 +154,7 @@ class ConnectionDescriptor: public EventableDescriptor
static int ReportErrorStatus (const unsigned long);
int SendOutboundData (const char*, int);
+ int SendWithoutCopying(const char*, int);
void SetConnectPending (bool f);
virtual void ScheduleClose (bool after_writing);
View
@@ -78,6 +78,7 @@ extern "C" {
int evma_get_connection_count();
int evma_send_data_to_connection (const unsigned long binding, const char *data, int data_length);
int evma_send_datagram (const unsigned long binding, const char *data, int data_length, const char *address, int port);
+ int evma_send_without_copying (const unsigned long binding, const char *data, int data_length);
float evma_get_comm_inactivity_timeout (const unsigned long binding);
int evma_set_comm_inactivity_timeout (const unsigned long binding, float value);
float evma_get_pending_connect_timeout (const unsigned long binding);
View
@@ -136,15 +136,10 @@ static VALUE t_send_special(int argc, VALUE *argv, VALUE self)
{
em_hook *hook = hook_from_obj(self, EM_SEND);
if (hook && hook->enabled && hook->send_func) {
+ // The buffer that the user assigns here must be something
+ // we can free, because we aren't going to copy it again.
em_data unit = (*hook->send_func)(argc, argv, hook->arg);
- // TODO
- // create a new path so we can queue a new outbound page by handing off this pointer
- // instead of having it memcpy'd in the C++ functions
- int sent_len = evma_send_data_to_connection (NUM2ULONG (rb_ivar_get(self, rb_intern("@signature"))), unit.data, unit.len);
- // the user has to understand that their pointer will be freed, otherwise we don't really
- // have a sensible way to manage it's lifecycle. once we create the new queueing path,
- // the pointer will just be freed after the page is written to the socket and this can go.
- free(unit.data);
+ int sent_len = evma_send_without_copying (NUM2ULONG (rb_ivar_get(self, rb_intern("@signature"))), unit.data, unit.len);
return INT2NUM (sent_len);
}
rb_raise(rb_eRuntimeError, "No hook object/function pointer has been assigned for send_special");

0 comments on commit 9b15eb6

Please sign in to comment.