Add a compatibility shim for working with libevent on MSVC
authorChristopher Dykes <cdykes@fb.com>
Wed, 11 May 2016 16:51:11 +0000 (09:51 -0700)
committerFacebook Github Bot 0 <facebook-github-bot-0-bot@fb.com>
Wed, 11 May 2016 17:05:37 +0000 (10:05 -0700)
Summary:
MSVC builds of libevent expect `evutil_socket_t` to be `HANDLE` values, but Folly, HHVM, and Thrift all use them as file descriptors.
This adds a `folly_event_set` function that always expects a file descriptor rather than a socket. This also changes the places in Folly that use it.

Reviewed By: mzlee, yfeldblum

Differential Revision: D2874655

fbshipit-source-id: 66cfd86fd69a9fbac30d150445e4814cd5ca799e

folly/Makefile.am
folly/io/async/AsyncSignalHandler.cpp
folly/io/async/AsyncSignalHandler.h
folly/io/async/AsyncTimeout.cpp
folly/io/async/AsyncTimeout.h
folly/io/async/EventHandler.cpp
folly/io/async/EventHandler.h
folly/portability/Event.h [new file with mode: 0644]

index d6511ccd571236aecf55e88c79188b9469b9c51f..3b248629b3f00c01699f63674a56fe28c4e445fc 100644 (file)
@@ -278,6 +278,7 @@ nobase_follyinclude_HEADERS = \
        portability/Constexpr.h \
        portability/Dirent.h \
        portability/Environment.h \
+       portability/Event.h \
        portability/Fcntl.h \
        portability/GFlags.h \
        portability/IOVec.h \
index 3fd19db9f34905b175fe82eaf6312f910c8c65c5..c8197cc8cddd725f2b68d097ab9d86564df6eb5e 100644 (file)
@@ -80,7 +80,7 @@ void AsyncSignalHandler::unregisterSignalHandler(int signum) {
   signalEvents_.erase(it);
 }
 
-void AsyncSignalHandler::libeventCallback(int signum,
+void AsyncSignalHandler::libeventCallback(libevent_fd_t signum,
                                           short /* events */,
                                           void* arg) {
   AsyncSignalHandler* handler = static_cast<AsyncSignalHandler*>(arg);
index 0b0c49b112b1408a64190a61b717f138b96aa837..213197e0fc28f2a23e190495c022c58fd74cf4ef 100644 (file)
@@ -83,7 +83,7 @@ class AsyncSignalHandler {
   AsyncSignalHandler(AsyncSignalHandler const &);
   AsyncSignalHandler& operator=(AsyncSignalHandler const &);
 
-  static void libeventCallback(int signum, short events, void* arg);
+  static void libeventCallback(libevent_fd_t signum, short events, void* arg);
 
   EventBase* eventBase_;
   SignalEventMap signalEvents_;
index 6758aec7660737e081f9d1af9d25a554c7642757..e4375f41ca130af2dc24f8f897ec77abf0e97613 100644 (file)
@@ -31,7 +31,8 @@ namespace folly {
 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
     : timeoutManager_(timeoutManager) {
 
-  event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
+  folly_event_set(
+      &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
   event_.ev_base = nullptr;
   timeoutManager_->attachTimeoutManager(
       this,
@@ -42,7 +43,8 @@ AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
     : timeoutManager_(eventBase) {
 
-  event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
+  folly_event_set(
+      &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
   event_.ev_base = nullptr;
   if (eventBase) {
     timeoutManager_->attachTimeoutManager(
@@ -56,7 +58,8 @@ AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
                              InternalEnum internal)
     : timeoutManager_(timeoutManager) {
 
-  event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
+  folly_event_set(
+      &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
   event_.ev_base = nullptr;
   timeoutManager_->attachTimeoutManager(this, internal);
   RequestContext::saveContext();
@@ -65,14 +68,16 @@ AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
     : timeoutManager_(eventBase) {
 
-  event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
+  folly_event_set(
+      &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
   event_.ev_base = nullptr;
   timeoutManager_->attachTimeoutManager(this, internal);
   RequestContext::saveContext();
 }
 
 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
-  event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
+  folly_event_set(
+      &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
   event_.ev_base = nullptr;
   RequestContext::saveContext();
 }
@@ -138,9 +143,9 @@ void AsyncTimeout::detachEventBase() {
   detachTimeoutManager();
 }
 
-void AsyncTimeout::libeventCallback(int fd, short events, void* arg) {
+void AsyncTimeout::libeventCallback(libevent_fd_t fd, short events, void* arg) {
   AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
-  assert(fd == -1);
+  assert(libeventFdToFd(fd) == -1);
   assert(events == EV_TIMEOUT);
   // prevent unused variable warnings
   (void)fd;
index 62b104551dbc5ff3b0ccf0b6d21a9d2dc8b72d4e..0c86ef746d305dea7b1ebefdb8932855ef9cfb4b 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <folly/io/async/TimeoutManager.h>
 
+#include <folly/portability/Event.h>
+
 #include <boost/noncopyable.hpp>
 #include <event.h>
 #include <memory>
@@ -219,7 +221,7 @@ class AsyncTimeout : private boost::noncopyable {
   );
 
  private:
-  static void libeventCallback(int fd, short events, void* arg);
+  static void libeventCallback(libevent_fd_t fd, short events, void* arg);
 
   struct event event_;
 
index a0ac4a8fa6119efc5f6e8148547179002ecbcfa3..c97b0d164dc6c9c949f752a6e1cc47a23370cc9c 100644 (file)
@@ -26,7 +26,7 @@
 namespace folly {
 
 EventHandler::EventHandler(EventBase* eventBase, int fd) {
-  event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
+  folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
   if (eventBase != nullptr) {
     setEventBase(eventBase);
   } else {
@@ -124,13 +124,13 @@ void EventHandler::changeHandlerFD(int fd) {
   ensureNotRegistered(__func__);
   // event_set() resets event_base.ev_base, so manually restore it afterwards
   struct event_base* evb = event_.ev_base;
-  event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
+  folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
   event_.ev_base = evb; // don't use event_base_set(), since evb may be nullptr
 }
 
 void EventHandler::initHandler(EventBase* eventBase, int fd) {
   ensureNotRegistered(__func__);
-  event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
+  folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
   setEventBase(eventBase);
 }
 
@@ -144,7 +144,7 @@ void EventHandler::ensureNotRegistered(const char* fn) {
   }
 }
 
-void EventHandler::libeventCallback(int fd, short events, void* arg) {
+void EventHandler::libeventCallback(libevent_fd_t fd, short events, void* arg) {
   EventHandler* handler = reinterpret_cast<EventHandler*>(arg);
   assert(fd == handler->event_.ev_fd);
   (void)fd; // prevent unused variable warnings
index 18493304055d15daffaf47958b67a7019aeead7b..af50c36eaec7a475a044c954e7557c78e6c16922 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <glog/logging.h>
 #include <folly/io/async/EventUtil.h>
+#include <folly/portability/Event.h>
 #include <boost/noncopyable.hpp>
 #include <stddef.h>
 
@@ -177,7 +178,7 @@ class EventHandler : private boost::noncopyable {
 
   void setEventBase(EventBase* eventBase);
 
-  static void libeventCallback(int fd, short events, void* arg);
+  static void libeventCallback(libevent_fd_t fd, short events, void* arg);
 
   struct event event_;
   EventBase* eventBase_;
diff --git a/folly/portability/Event.h b/folly/portability/Event.h
new file mode 100644 (file)
index 0000000..f921cd5
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <event.h>
+
+#ifdef _MSC_VER
+# include <event2/event_compat.h>
+# include <folly/portability/Fcntl.h>
+# include <folly/portability/Windows.h>
+#endif
+
+namespace folly {
+#ifdef _MSC_VER
+using libevent_fd_t = evutil_socket_t;
+#else
+using libevent_fd_t = int;
+#endif
+
+inline libevent_fd_t getLibeventFd(int fd) {
+#ifdef _MSC_VER
+  if (fd == -1) {
+    return (libevent_fd_t)INVALID_HANDLE_VALUE;
+  }
+  return _get_osfhandle(fd);
+#else
+  return fd;
+#endif
+}
+
+inline int libeventFdToFd(libevent_fd_t fd) {
+#ifdef _MSC_VER
+  if (fd == (libevent_fd_t)INVALID_HANDLE_VALUE) {
+    return -1;
+  }
+  return _open_osfhandle((intptr_t)fd, O_RDWR | O_BINARY);
+#else
+  return fd;
+#endif
+}
+
+using EventSetCallback = void (*)(libevent_fd_t, short, void*);
+inline void
+folly_event_set(event* e, int fd, short s, EventSetCallback f, void* arg) {
+  auto lfd = getLibeventFd(fd);
+  event_set(e, lfd, s, f, arg);
+}
+}