From 6e75c507e1bb27e44f205a4ee3e1b138bbbff5ab Mon Sep 17 00:00:00 2001
From: Aman Gupta <aman@tmm1.net>
Date: Mon, 9 Feb 2015 23:59:11 -0800
Subject: [PATCH 11/11] allocate one SelectData_t per reactor to avoid heap
 allocation on every tick

Conflicts:
	ext/em.cpp
---
 ext/em.cpp | 43 ++++++++++++++++++++-----------------------
 ext/em.h   |  3 ++-
 2 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/ext/em.cpp b/ext/em.cpp
index 315d7d7..326dbe8 100644
--- a/ext/em.cpp
+++ b/ext/em.cpp
@@ -101,6 +101,7 @@ EventMachine_t::EventMachine_t (EMCallback event_callback):
 	#endif
 
 	_InitializeLoopBreaker();
+	SelectData = new SelectData_t();
 }
 
 
@@ -130,6 +131,8 @@ EventMachine_t::~EventMachine_t()
 		close (epfd);
 	if (kqfd != -1)
 		close (kqfd);
+
+	delete SelectData;
 }
 
 
@@ -856,24 +859,18 @@ void EventMachine_t::_RunSelectOnce()
 	// epoll will be effective if we provide it as an alternative,
 	// however it has the same problem interoperating with Ruby
 	// threads that select does.
-
-	SelectData_t SelectData;
-	/*
-	fd_set fdreads, fdwrites;
-	FD_ZERO (&fdreads);
-	FD_ZERO (&fdwrites);
-
-	int maxsocket = 0;
-	*/
+	rb_fd_zero (&SelectData->fdreads);
+	rb_fd_zero (&SelectData->fdwrites);
+	rb_fd_zero (&SelectData->fderrors);
 
 	// Always read the loop-breaker reader.
 	// Changed 23Aug06, provisionally implemented for Windows with a UDP socket
 	// running on localhost with a randomly-chosen port. (*Puke*)
 	// Windows has a version of the Unix pipe() library function, but it doesn't
 	// give you back descriptors that are selectable.
-	rb_fd_set (LoopBreakerReader, &(SelectData.fdreads));
-	if (SelectData.maxsocket < LoopBreakerReader)
-		SelectData.maxsocket = LoopBreakerReader;
+	rb_fd_set (LoopBreakerReader, &(SelectData->fdreads));
+	if (SelectData->maxsocket < LoopBreakerReader)
+		SelectData->maxsocket = LoopBreakerReader;
 
 	// prepare the sockets for reading and writing
 	size_t i;
@@ -886,27 +883,27 @@ void EventMachine_t::_RunSelectOnce()
 		assert (sd != INVALID_SOCKET);
 
 		if (ed->SelectForRead())
-			rb_fd_set (sd, &(SelectData.fdreads));
+			rb_fd_set (sd, &(SelectData->fdreads));
 		if (ed->SelectForWrite())
-			rb_fd_set (sd, &(SelectData.fdwrites));
+			rb_fd_set (sd, &(SelectData->fdwrites));
 
 		#ifdef OS_WIN32
 		/* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
 		   Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
 		*/
-		rb_fd_set (sd, &(SelectData.fderrors));
+		rb_fd_set (sd, &(SelectData->fderrors));
 		#endif
 
-		if (SelectData.maxsocket < sd)
-			SelectData.maxsocket = sd;
+		if (SelectData->maxsocket < sd)
+			SelectData->maxsocket = sd;
 	}
 
 
 	{ // read and write the sockets
 		//timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000.
 		//timeval tv = Quantum;
-		SelectData.tv = _TimeTilNextEvent();
-		int s = SelectData._Select();
+		SelectData->tv = _TimeTilNextEvent();
+		int s = SelectData->_Select();
 		//rb_thread_blocking_region(xxx,(void*)&SelectData,RUBY_UBF_IO,0);
 		//int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads), &(SelectData.fdwrites), NULL, &(SelectData.tv));
 		//int s = SelectData.nSockets;
@@ -929,15 +926,15 @@ void EventMachine_t::_RunSelectOnce()
 					continue;
 				assert (sd != INVALID_SOCKET);
 
-				if (rb_fd_isset (sd, &(SelectData.fdwrites)))
+				if (rb_fd_isset (sd, &(SelectData->fdwrites)))
 					ed->Write();
-				if (rb_fd_isset (sd, &(SelectData.fdreads)))
+				if (rb_fd_isset (sd, &(SelectData->fdreads)))
 					ed->Read();
-				if (rb_fd_isset (sd, &(SelectData.fderrors)))
+				if (rb_fd_isset (sd, &(SelectData->fderrors)))
 					ed->HandleError();
 			}
 
-			if (rb_fd_isset (LoopBreakerReader, &(SelectData.fdreads)))
+			if (rb_fd_isset (LoopBreakerReader, &(SelectData->fdreads)))
 				_ReadLoopBreaker();
 		}
 		else if (s < 0) {
diff --git a/ext/em.h b/ext/em.h
index 86909ad..cdcca23 100644
--- a/ext/em.h
+++ b/ext/em.h
@@ -91,7 +91,7 @@ typedef fd_set rb_fdset_t;
 
 class EventableDescriptor;
 class InotifyDescriptor;
-
+struct SelectData_t;
 
 /********************
 class EventMachine_t
@@ -234,6 +234,7 @@ class EventMachine_t
 
 	private:
 		bool bTerminateSignalReceived;
+		SelectData_t *SelectData;
 
 		bool bEpoll;
 		int epfd; // Epoll file-descriptor
-- 
2.1.4

