diff agent/src/os/win32/Reaper.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/os/win32/Reaper.cpp	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+#include <iostream>
+#include "Reaper.hpp"
+
+using namespace std;
+
+Reaper::Reaper(ReaperCB* cb) {
+  InitializeCriticalSection(&crit);
+  event = CreateEvent(NULL, TRUE, FALSE, NULL);
+  this->cb = cb;
+
+  active = false;
+  shouldShutDown = false;
+}
+
+bool
+Reaper::start() {
+  bool result = false;
+
+  EnterCriticalSection(&crit);
+
+  if (!active) {
+    DWORD id;
+    HANDLE reaper = CreateThread(NULL, 0, &Reaper::reaperThreadEntry,
+                                 this, 0, &id);
+    if (reaper != NULL) {
+      result = true;
+    }
+  }
+
+  LeaveCriticalSection(&crit);
+
+  return result;
+}
+
+bool
+Reaper::stop() {
+  bool result = false;
+
+  EnterCriticalSection(&crit);
+
+  if (active) {
+    shouldShutDown = true;
+    SetEvent(event);
+    while (active) {
+      Sleep(1);
+    }
+    shouldShutDown = false;
+    result = true;
+  }
+
+  LeaveCriticalSection(&crit);
+
+  return result;
+}
+
+void
+Reaper::registerProcess(HANDLE processHandle, void* userData) {
+  ProcessInfo info;
+
+  info.handle = processHandle;
+  info.userData = userData;
+
+  EnterCriticalSection(&crit);
+
+  procInfo.push_back(info);
+  SetEvent(event);
+
+  LeaveCriticalSection(&crit);
+}
+
+void
+Reaper::reaperThread() {
+  while (!shouldShutDown) {
+    // Take atomic snapshot of the current process list and user data
+    EnterCriticalSection(&crit);
+
+    int num = procInfo.size();
+    HANDLE* handleList = new HANDLE[1 + num];
+    void**  dataList   = new void*[num];
+    for (int i = 0; i < num; i++) {
+      handleList[i] = procInfo[i].handle;
+      dataList[i]   = procInfo[i].userData;
+    }
+
+    LeaveCriticalSection(&crit);
+
+    // Topmost handle becomes the event object, so other threads can
+    // signal this one to notice differences in the above list (or
+    // shut down)
+    handleList[num] = event;
+
+    // Wait for these objects
+    DWORD idx = WaitForMultipleObjects(1 + num, handleList,
+                                       FALSE, INFINITE);
+    if ((idx >= WAIT_OBJECT_0) && (idx <= WAIT_OBJECT_0 + num)) {
+      idx -= WAIT_OBJECT_0;
+      if (idx < num) {
+        // A process exited (i.e., it wasn't that we were woken up
+        // just because the event went off)
+        (*cb)(dataList[idx]);
+        // Remove this process from the list (NOTE: requires that
+        // ordering does not change, i.e., that all additions are to
+        // the back of the process list)
+        EnterCriticalSection(&crit);
+
+        std::vector<ProcessInfo>::iterator iter = procInfo.begin();
+        iter += idx;
+        procInfo.erase(iter);
+
+        LeaveCriticalSection(&crit);
+      } else {
+        // Notification from other thread
+        ResetEvent(event);
+      }
+    } else {
+      // Unexpected return value. For now, warn.
+      cerr << "Reaper::reaperThread(): unexpected return value "
+           << idx << " from WaitForMultipleObjects" << endl;
+    }
+
+    // Clean up these lists
+    delete[] handleList;
+    delete[] dataList;
+  }
+
+  // Time to shut down
+  active = false;
+}
+
+DWORD WINAPI
+Reaper::reaperThreadEntry(LPVOID data) {
+  Reaper* reaper = (Reaper*) data;
+  reaper->reaperThread();
+  return 0;
+}