You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2013/05/29 19:41:06 UTC
[28/35] Renamed 'third_party' to '3rdparty'.
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/tests/os_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/os_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/os_tests.cpp
new file mode 100644
index 0000000..047778d
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/tests/os_tests.cpp
@@ -0,0 +1,208 @@
+#include <gtest/gtest.h>
+
+#include <gmock/gmock.h>
+
+#include <cstdlib> // For rand.
+#include <string>
+
+#include <stout/foreach.hpp>
+#include <stout/gtest.hpp>
+#include <stout/hashset.hpp>
+#include <stout/os.hpp>
+#include <stout/stopwatch.hpp>
+#include <stout/try.hpp>
+#include <stout/uuid.hpp>
+
+using std::string;
+
+
+static hashset<string> listfiles(const string& directory)
+{
+ hashset<string> fileset;
+ foreach (const string& file, os::ls(directory)) {
+ fileset.insert(file);
+ }
+ return fileset;
+}
+
+
+class OsTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ Try<string> mkdtemp = os::mkdtemp();
+ ASSERT_SOME(mkdtemp);
+ tmpdir = mkdtemp.get();
+ }
+
+ virtual void TearDown()
+ {
+ ASSERT_SOME(os::rmdir(tmpdir));
+ }
+
+ string tmpdir;
+};
+
+
+TEST_F(OsTest, rmdir)
+{
+ const hashset<string> EMPTY;
+
+ hashset<string> expectedListing = EMPTY;
+ EXPECT_EQ(expectedListing, listfiles(tmpdir));
+
+ os::mkdir(tmpdir + "/a/b/c");
+ os::mkdir(tmpdir + "/a/b/d");
+ os::mkdir(tmpdir + "/e/f");
+
+ expectedListing = EMPTY;
+ expectedListing.insert("a");
+ expectedListing.insert("e");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir));
+
+ expectedListing = EMPTY;
+ expectedListing.insert("b");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a"));
+
+ expectedListing = EMPTY;
+ expectedListing.insert("c");
+ expectedListing.insert("d");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a/b"));
+
+ expectedListing = EMPTY;
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a/b/c"));
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a/b/d"));
+
+ expectedListing.insert("f");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/e"));
+
+ expectedListing = EMPTY;
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/e/f"));
+}
+
+
+TEST_F(OsTest, nonblock)
+{
+ int pipes[2];
+ ASSERT_NE(-1, pipe(pipes));
+
+ Try<bool> isNonBlock = false;
+
+ isNonBlock = os::isNonblock(pipes[0]);
+ ASSERT_SOME(isNonBlock);
+ EXPECT_FALSE(isNonBlock.get());
+
+ ASSERT_SOME(os::nonblock(pipes[0]));
+
+ isNonBlock = os::isNonblock(pipes[0]);
+ ASSERT_SOME(isNonBlock);
+ EXPECT_TRUE(isNonBlock.get());
+
+ close(pipes[0]);
+ close(pipes[1]);
+
+ EXPECT_ERROR(os::nonblock(pipes[0]));
+ EXPECT_ERROR(os::nonblock(pipes[0]));
+}
+
+
+TEST_F(OsTest, touch)
+{
+ const string& testfile = tmpdir + "/" + UUID::random().toString();
+
+ ASSERT_SOME(os::touch(testfile));
+ ASSERT_TRUE(os::exists(testfile));
+}
+
+
+TEST_F(OsTest, readWriteString)
+{
+ const string& testfile = tmpdir + "/" + UUID::random().toString();
+ const string& teststr = "test";
+
+ ASSERT_SOME(os::write(testfile, teststr));
+
+ Try<string> readstr = os::read(testfile);
+
+ ASSERT_SOME(readstr);
+ EXPECT_EQ(teststr, readstr.get());
+}
+
+
+TEST_F(OsTest, find)
+{
+ const string& testdir = tmpdir + "/" + UUID::random().toString();
+ const string& subdir = testdir + "/test1";
+ ASSERT_SOME(os::mkdir(subdir)); // Create the directories.
+
+ // Now write some files.
+ const string& file1 = testdir + "/file1.txt";
+ const string& file2 = subdir + "/file2.txt";
+ const string& file3 = subdir + "/file3.jpg";
+
+ ASSERT_SOME(os::touch(file1));
+ ASSERT_SOME(os::touch(file2));
+ ASSERT_SOME(os::touch(file3));
+
+ // Find "*.txt" files.
+ Try<std::list<string> > result = os::find(testdir, ".txt");
+ ASSERT_SOME(result);
+
+ hashset<string> files;
+ foreach (const string& file, result.get()) {
+ files.insert(file);
+ }
+
+ ASSERT_EQ(2u, files.size());
+ ASSERT_TRUE(files.contains(file1));
+ ASSERT_TRUE(files.contains(file2));
+}
+
+
+TEST_F(OsTest, uname)
+{
+ Try<os::UTSInfo> info = os::uname();
+
+ ASSERT_SOME(info);
+#ifdef __linux__
+ EXPECT_EQ(info.get().sysname, "Linux");
+#endif
+#ifdef __APPLE__
+ EXPECT_EQ(info.get().sysname, "Darwin");
+#endif
+}
+
+
+TEST_F(OsTest, sysname)
+{
+ Try<string> name = os::sysname();
+
+ ASSERT_SOME(name);
+#ifdef __linux__
+ EXPECT_EQ(name.get(), "Linux");
+#endif
+#ifdef __APPLE__
+ EXPECT_EQ(name.get(), "Darwin");
+#endif
+}
+
+
+TEST_F(OsTest, release)
+{
+ Try<os::Release> info = os::release();
+
+ ASSERT_SOME(info);
+}
+
+
+TEST_F(OsTest, sleep)
+{
+ Duration duration = Milliseconds(10);
+ Stopwatch stopwatch;
+ stopwatch.start();
+ ASSERT_SOME(os::sleep(duration));
+ ASSERT_LE(duration, stopwatch.elapsed());
+
+ ASSERT_ERROR(os::sleep(Milliseconds(-10)));
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/tests/proc_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/proc_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/proc_tests.cpp
new file mode 100644
index 0000000..2305ef5
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/tests/proc_tests.cpp
@@ -0,0 +1,162 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <unistd.h> // For getpid, getppid.
+
+#include <gmock/gmock.h>
+
+#include <set>
+
+#include <stout/gtest.hpp>
+#include <stout/proc.hpp>
+#include <stout/try.hpp>
+
+using proc::CPU;
+using proc::SystemStatus;
+using proc::ProcessStatus;
+
+using std::set;
+
+
+TEST(ProcTest, pids)
+{
+ Try<set<pid_t> > pids = proc::pids();
+
+ ASSERT_SOME(pids);
+ EXPECT_NE(0u, pids.get().size());
+ EXPECT_EQ(1u, pids.get().count(getpid()));
+ EXPECT_EQ(1u, pids.get().count(1));
+}
+
+
+TEST(ProcTest, children)
+{
+ Try<set<pid_t> > children = proc::children(getpid());
+
+ ASSERT_SOME(children);
+ EXPECT_EQ(0u, children.get().size());
+
+ // Use pipes to determine the pids of the child and grandchild.
+ int childPipes[2];
+ int grandchildPipes[2];
+ ASSERT_NE(-1, pipe(childPipes));
+ ASSERT_NE(-1, pipe(grandchildPipes));
+
+ pid_t childPid;
+ pid_t grandchildPid;
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+
+ if (pid > 0) {
+ // In parent process.
+ close(childPipes[1]);
+ close(grandchildPipes[1]);
+
+ // Get the pids via the pipes.
+ ASSERT_NE(
+ -1,
+ read(childPipes[0], &childPid, sizeof(childPid)));
+ ASSERT_NE(
+ -1,
+ read(grandchildPipes[0], &grandchildPid, sizeof(grandchildPid)));
+
+ close(childPipes[0]);
+ close(grandchildPipes[0]);
+ } else {
+ // In child process.
+ close(childPipes[0]);
+ close(grandchildPipes[0]);
+
+ // Double fork!
+ if ((pid = fork()) == -1) {
+ perror("Failed to fork a grand child process");
+ abort();
+ }
+
+ if (pid > 0) {
+ // Still in child process.
+ pid = getpid();
+ if (write(childPipes[1], &pid, sizeof(pid)) != sizeof(pid)) {
+ perror("Failed to write PID on pipe");
+ abort();
+ }
+
+ close(childPipes[1]);
+
+ while (true); // Keep waiting until we get a signal.
+ } else {
+ // In grandchild process.
+ pid = getpid();
+ if (write(grandchildPipes[1], &pid, sizeof(pid)) != sizeof(pid)) {
+ perror("Failed to write PID on pipe");
+ abort();
+ }
+
+ close(grandchildPipes[1]);
+
+ while (true); // Keep waiting until we get a signal.
+ }
+ }
+
+ // Ensure the non-recursive children does not include the
+ // grandchild.
+ children = proc::children(getpid(), false);
+
+ ASSERT_SOME(children);
+ EXPECT_EQ(1u, children.get().size());
+ EXPECT_EQ(1u, children.get().count(childPid));
+
+ children = proc::children(getpid());
+
+ ASSERT_SOME(children);
+ EXPECT_EQ(2u, children.get().size());
+ EXPECT_EQ(1u, children.get().count(childPid));
+ EXPECT_EQ(1u, children.get().count(grandchildPid));
+
+ // Cleanup by killing the descendants.
+ EXPECT_EQ(0, kill(grandchildPid, SIGKILL));
+ EXPECT_EQ(0, kill(childPid, SIGKILL));
+}
+
+
+TEST(ProcTest, cpus)
+{
+ Try<std::list<CPU> > cpus = proc::cpus();
+
+ ASSERT_SOME(cpus);
+ EXPECT_LE(1u, cpus.get().size());
+}
+
+
+TEST(ProcTest, SystemStatus)
+{
+ Try<SystemStatus> status = proc::status();
+
+ ASSERT_SOME(status);
+ EXPECT_NE(0u, status.get().btime);
+}
+
+
+TEST(ProcTest, ProcessStatus)
+{
+ Try<ProcessStatus> status = proc::status(getpid());
+
+ ASSERT_SOME(status);
+ EXPECT_EQ(getpid(), status.get().pid);
+ EXPECT_EQ(getppid(), status.get().ppid);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/tests/strings_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/strings_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/strings_tests.cpp
new file mode 100644
index 0000000..7ec9446
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/tests/strings_tests.cpp
@@ -0,0 +1,255 @@
+#include <gtest/gtest.h>
+
+#include <gmock/gmock.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <stout/format.hpp>
+#include <stout/gtest.hpp>
+#include <stout/strings.hpp>
+#include <stout/try.hpp>
+
+using std::map;
+using std::string;
+using std::vector;
+
+
+TEST(StringsTest, Format)
+{
+ Try<std::string> result = strings::format("%s %s", "hello", "world");
+ ASSERT_SOME(result);
+ EXPECT_EQ("hello world", result.get());
+
+ result = strings::format("hello %d", 42);
+ ASSERT_SOME(result);
+ EXPECT_EQ("hello 42", result.get());
+
+ result = strings::format("hello %s", "fourty-two");
+ ASSERT_SOME(result);
+ EXPECT_EQ("hello fourty-two", result.get());
+
+ string hello = "hello";
+
+ result = strings::format("%s %s", hello, "fourty-two");
+ ASSERT_SOME(result);
+ EXPECT_EQ("hello fourty-two", result.get());
+}
+
+
+TEST(StringsTest, Remove)
+{
+ EXPECT_EQ("heo word", strings::remove("hello world", "l"));
+ EXPECT_EQ("hel world", strings::remove("hello world", "lo"));
+ EXPECT_EQ("home/", strings::remove("/home/", "/", strings::PREFIX));
+ EXPECT_EQ("/home", strings::remove("/home/", "/", strings::SUFFIX));
+}
+
+
+TEST(StringsTest, Replace)
+{
+ EXPECT_EQ("hello*", strings::replace("hello/", "/", "*"));
+ EXPECT_EQ("*hello", strings::replace("/hello", "/", "*"));
+ EXPECT_EQ("*hello*world*", strings::replace("/hello/world/", "/", "*"));
+ EXPECT_EQ("*", strings::replace("/", "/", "*"));
+ EXPECT_EQ("hello world", strings::replace("hello world", "/", "*"));
+ EXPECT_EQ("***1***2***3***", strings::replace("/1/2/3/", "/", "***"));
+ EXPECT_EQ("123", strings::replace("/1/2/3/", "/", ""));
+ EXPECT_EQ("/1/2/3**", strings::replace("***1***2***3**", "***", "/"));
+ EXPECT_EQ("/1/2/3/", strings::replace("/1/2/3/", "", "*"));
+}
+
+
+TEST(StringsTest, Trim)
+{
+ EXPECT_EQ("", strings::trim("", " "));
+ EXPECT_EQ("", strings::trim(" ", " "));
+ EXPECT_EQ("hello world", strings::trim("hello world", " "));
+ EXPECT_EQ("hello world", strings::trim(" hello world", " "));
+ EXPECT_EQ("hello world", strings::trim("hello world ", " "));
+ EXPECT_EQ("hello world", strings::trim(" hello world ", " "));
+ EXPECT_EQ("hello world", strings::trim(" \t hello world\t ", " \t"));
+ EXPECT_EQ("hello world", strings::trim(" \t hello world\t \n\r "));
+}
+
+
+TEST(StringsTest, Tokenize)
+{
+ vector<string> tokens = strings::tokenize("hello world, what's up?", " ");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("hello", tokens[0]);
+ EXPECT_EQ("world,", tokens[1]);
+ EXPECT_EQ("what's", tokens[2]);
+ EXPECT_EQ("up?", tokens[3]);
+}
+
+
+TEST(StringsTest, TokenizeStringWithDelimsAtStart)
+{
+ vector<string> tokens = strings::tokenize(" hello world, what's up?", " ");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("hello", tokens[0]);
+ EXPECT_EQ("world,", tokens[1]);
+ EXPECT_EQ("what's", tokens[2]);
+ EXPECT_EQ("up?", tokens[3]);
+}
+
+
+TEST(StringsTest, TokenizeStringWithDelimsAtEnd)
+{
+ vector<string> tokens = strings::tokenize("hello world, what's up? ", " ");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("hello", tokens[0]);
+ EXPECT_EQ("world,", tokens[1]);
+ EXPECT_EQ("what's", tokens[2]);
+ EXPECT_EQ("up?", tokens[3]);
+}
+
+
+TEST(StringsTest, TokenizeStringWithDelimsAtStartAndEnd)
+{
+ vector<string> tokens = strings::tokenize(" hello world, what's up? ", " ");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("hello", tokens[0]);
+ EXPECT_EQ("world,", tokens[1]);
+ EXPECT_EQ("what's", tokens[2]);
+ EXPECT_EQ("up?", tokens[3]);
+}
+
+
+TEST(StringsTest, TokenizeWithMultipleDelims)
+{
+ vector<string> tokens = strings::tokenize("hello\tworld, \twhat's up?",
+ " \t");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("hello", tokens[0]);
+ EXPECT_EQ("world,", tokens[1]);
+ EXPECT_EQ("what's", tokens[2]);
+ EXPECT_EQ("up?", tokens[3]);
+}
+
+
+TEST(StringsTest, TokenizeEmptyString)
+{
+ vector<string> tokens = strings::tokenize("", " ");
+ ASSERT_EQ(0u, tokens.size());
+}
+
+
+TEST(StringsTest, TokenizeDelimOnlyString)
+{
+ vector<string> tokens = strings::tokenize(" ", " ");
+ ASSERT_EQ(0u, tokens.size());
+}
+
+
+TEST(StringsTest, SplitEmptyString)
+{
+ vector<string> tokens = strings::split("", ",");
+ ASSERT_EQ(1u, tokens.size());
+ EXPECT_EQ("", tokens[0]);
+}
+
+
+TEST(StringsTest, SplitDelimOnlyString)
+{
+ vector<string> tokens = strings::split(",,,", ",");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("", tokens[0]);
+ EXPECT_EQ("", tokens[1]);
+ EXPECT_EQ("", tokens[2]);
+ EXPECT_EQ("", tokens[3]);
+}
+
+
+TEST(StringsTest, Split)
+{
+ vector<string> tokens = strings::split("foo,bar,,baz", ",");
+ ASSERT_EQ(4u, tokens.size());
+ EXPECT_EQ("foo", tokens[0]);
+ EXPECT_EQ("bar", tokens[1]);
+ EXPECT_EQ("", tokens[2]);
+ EXPECT_EQ("baz", tokens[3]);
+}
+
+
+TEST(StringsTest, SplitStringWithDelimsAtStart)
+{
+ vector<string> tokens = strings::split(",,foo,bar,,baz", ",");
+ ASSERT_EQ(6u, tokens.size());
+ EXPECT_EQ("", tokens[0]);
+ EXPECT_EQ("", tokens[1]);
+ EXPECT_EQ("foo", tokens[2]);
+ EXPECT_EQ("bar", tokens[3]);
+ EXPECT_EQ("", tokens[4]);
+ EXPECT_EQ("baz", tokens[5]);
+}
+
+
+TEST(StringsTest, SplitStringWithDelimsAtEnd)
+{
+ vector<string> tokens = strings::split("foo,bar,,baz,,", ",");
+ ASSERT_EQ(6u, tokens.size());
+ EXPECT_EQ("foo", tokens[0]);
+ EXPECT_EQ("bar", tokens[1]);
+ EXPECT_EQ("", tokens[2]);
+ EXPECT_EQ("baz", tokens[3]);
+ EXPECT_EQ("", tokens[4]);
+ EXPECT_EQ("", tokens[5]);
+}
+
+
+TEST(StringsTest, SplitStringWithDelimsAtStartAndEnd)
+{
+ vector<string> tokens = strings::split(",,foo,bar,,", ",");
+ ASSERT_EQ(6u, tokens.size());
+ EXPECT_EQ("", tokens[0]);
+ EXPECT_EQ("", tokens[1]);
+ EXPECT_EQ("foo", tokens[2]);
+ EXPECT_EQ("bar", tokens[3]);
+ EXPECT_EQ("", tokens[4]);
+ EXPECT_EQ("", tokens[5]);
+}
+
+
+TEST(StringsTest, SplitWithMultipleDelims)
+{
+ vector<string> tokens = strings::split("foo.bar,.,.baz.", ",.");
+ ASSERT_EQ(7u, tokens.size());
+ EXPECT_EQ("foo", tokens[0]);
+ EXPECT_EQ("bar", tokens[1]);
+ EXPECT_EQ("", tokens[2]);
+ EXPECT_EQ("", tokens[3]);
+ EXPECT_EQ("", tokens[4]);
+ EXPECT_EQ("baz", tokens[5]);
+ EXPECT_EQ("", tokens[6]);
+}
+
+
+TEST(StringsTest, Pairs)
+{
+ map<string, vector<string> > pairs = strings::pairs("one=1,two=2", ",", "=");
+ ASSERT_EQ(2u, pairs.size());
+ ASSERT_EQ(1u, pairs.count("one"));
+ ASSERT_EQ(1u, pairs["one"].size());
+ EXPECT_EQ("1", pairs["one"].front());
+ ASSERT_EQ(1u, pairs.count("two"));
+ ASSERT_EQ(1u, pairs["two"].size());
+ EXPECT_EQ("2", pairs["two"].front());
+}
+
+
+TEST(StringsTest, StartsWith)
+{
+ EXPECT_TRUE(strings::startsWith("hello world", "hello"));
+ EXPECT_FALSE(strings::startsWith("hello world", "no"));
+ EXPECT_FALSE(strings::startsWith("hello world", "ello"));
+}
+
+
+TEST(StringsTest, Contains)
+{
+ EXPECT_TRUE(strings::contains("hello world", "world"));
+ EXPECT_FALSE(strings::contains("hello world", "no"));
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/stout/tests/uuid_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/uuid_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/uuid_tests.cpp
new file mode 100644
index 0000000..ad1d986
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/tests/uuid_tests.cpp
@@ -0,0 +1,37 @@
+#include <gtest/gtest.h>
+
+#include <gmock/gmock.h>
+
+#include <string>
+
+#include <stout/uuid.hpp>
+
+using std::string;
+
+
+TEST(UUIDTest, test)
+{
+ UUID uuid1 = UUID::random();
+ UUID uuid2 = UUID::fromBytes(uuid1.toBytes());
+ UUID uuid3 = uuid2;
+
+ EXPECT_EQ(uuid1, uuid2);
+ EXPECT_EQ(uuid2, uuid3);
+ EXPECT_EQ(uuid1, uuid3);
+
+ string bytes1 = uuid1.toBytes();
+ string bytes2 = uuid2.toBytes();
+ string bytes3 = uuid3.toBytes();
+
+ EXPECT_EQ(bytes1, bytes2);
+ EXPECT_EQ(bytes2, bytes3);
+ EXPECT_EQ(bytes1, bytes3);
+
+ string string1 = uuid1.toString();
+ string string2 = uuid2.toString();
+ string string3 = uuid3.toString();
+
+ EXPECT_EQ(string1, string2);
+ EXPECT_EQ(string2, string3);
+ EXPECT_EQ(string1, string3);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/3rdparty/versions.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/versions.am b/3rdparty/libprocess/3rdparty/versions.am
new file mode 100644
index 0000000..0d05698
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/versions.am
@@ -0,0 +1,11 @@
+# This automake utility file is included from 3rdparty/Makefile.am
+# and src/Makefile.am, so we can update the version numbers of
+# third_party packages in exactly one place.
+
+BOOST_VERSION = 1.53.0
+GLOG_VERSION = 0.3.1
+GMOCK_VERSION = 1.6.0
+GPERFTOOLS_VERSION = 2.0
+LIBEV_VERSION = 4.15
+PROTOBUF_VERSION = 2.4.1
+RY_HTTP_PARSER_VERSION = 1c3624a
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/LICENSE
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/LICENSE b/3rdparty/libprocess/LICENSE
new file mode 100644
index 0000000..f433b1a
--- /dev/null
+++ b/3rdparty/libprocess/LICENSE
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/Makefile.am b/3rdparty/libprocess/Makefile.am
new file mode 100644
index 0000000..b6b8abd
--- /dev/null
+++ b/3rdparty/libprocess/Makefile.am
@@ -0,0 +1,125 @@
+# Makefile for libprocess. Note that 3rdparty needs to be built
+# first (see 3rdparty/Makefile.am).
+
+ACLOCAL_AMFLAGS = -I m4
+
+AUTOMAKE_OPTIONS = foreign
+
+SUBDIRS = 3rdparty .
+
+include 3rdparty/versions.am
+
+STOUT = 3rdparty/stout
+BOOST = 3rdparty/boost-$(BOOST_VERSION)
+GLOG = 3rdparty/glog-$(GLOG_VERSION)
+GMOCK = 3rdparty/gmock-$(GMOCK_VERSION)
+GPERFTOOLS = 3rdparty/gperftools-$(GPERFTOOLS_VERSION)
+GTEST = $(GMOCK)/gtest
+RY_HTTP_PARSER = 3rdparty/ry-http-parser-$(RY_HTTP_PARSER_VERSION)
+LIBEV = 3rdparty/libev-$(LIBEV_VERSION)
+
+
+# Library. It is not installable presently because most people link
+# the libprocess statically into their resulting library or binary and
+# don't want any parts of libprocess to get installed (which happens
+# even if you attempt to do conditional installation via configure
+# arguments, see configure.ac).
+noinst_LTLIBRARIES = libprocess.la
+
+libprocess_la_SOURCES = \
+ src/config.hpp \
+ src/decoder.hpp \
+ src/encoder.hpp \
+ src/gate.hpp \
+ src/latch.cpp \
+ src/pid.cpp \
+ src/process.cpp \
+ src/statistics.cpp \
+ src/synchronized.hpp
+
+libprocess_la_CPPFLAGS = \
+ -I$(srcdir)/include \
+ -I$(srcdir)/$(STOUT)/include \
+ -I$(BOOST) \
+ -I$(GLOG)/src \
+ -I$(LIBEV) \
+ -I$(RY_HTTP_PARSER) \
+ $(AM_CPPFLAGS)
+
+libprocess_la_LIBADD = \
+ $(GLOG)/libglog.la \
+ 3rdparty/libry_http_parser.la \
+ $(LIBEV)/libev.la
+
+if HAS_GPERFTOOLS
+libprocess_la_CPPFLAGS += -I$(GPERFTOOLS)/src
+libprocess_la_LIBADD += $(GPERFTOOLS)/libprofiler.la
+endif
+
+# Headers.
+libprocess_la_SOURCES += \
+ $(top_srcdir)/include/process/async.hpp \
+ $(top_srcdir)/include/process/clock.hpp \
+ $(top_srcdir)/include/process/collect.hpp \
+ $(top_srcdir)/include/process/defer.hpp \
+ $(top_srcdir)/include/process/deferred.hpp \
+ $(top_srcdir)/include/process/delay.hpp \
+ $(top_srcdir)/include/process/dispatch.hpp \
+ $(top_srcdir)/include/process/event.hpp \
+ $(top_srcdir)/include/process/executor.hpp \
+ $(top_srcdir)/include/process/filter.hpp \
+ $(top_srcdir)/include/process/future.hpp \
+ $(top_srcdir)/include/process/gc.hpp \
+ $(top_srcdir)/include/process/gmock.hpp \
+ $(top_srcdir)/include/process/gtest.hpp \
+ $(top_srcdir)/include/process/http.hpp \
+ $(top_srcdir)/include/process/id.hpp \
+ $(top_srcdir)/include/process/io.hpp \
+ $(top_srcdir)/include/process/latch.hpp \
+ $(top_srcdir)/include/process/logging.hpp \
+ $(top_srcdir)/include/process/message.hpp \
+ $(top_srcdir)/include/process/mime.hpp \
+ $(top_srcdir)/include/process/once.hpp \
+ $(top_srcdir)/include/process/pid.hpp \
+ $(top_srcdir)/include/process/process.hpp \
+ $(top_srcdir)/include/process/profiler.hpp \
+ $(top_srcdir)/include/process/protobuf.hpp \
+ $(top_srcdir)/include/process/run.hpp \
+ $(top_srcdir)/include/process/socket.hpp \
+ $(top_srcdir)/include/process/statistics.hpp \
+ $(top_srcdir)/include/process/thread.hpp \
+ $(top_srcdir)/include/process/time.hpp \
+ $(top_srcdir)/include/process/timeout.hpp \
+ $(top_srcdir)/include/process/timer.hpp
+
+# Tests.
+check_PROGRAMS = tests
+
+tests_SOURCES = \
+ src/tests/decoder_tests.cpp \
+ src/tests/encoder_tests.cpp \
+ src/tests/http_tests.cpp \
+ src/tests/io_tests.cpp \
+ src/tests/main.cpp \
+ src/tests/process_tests.cpp \
+ src/tests/statistics_tests.cpp \
+ src/tests/time_tests.cpp
+
+tests_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(GTEST)/include \
+ -I$(GMOCK)/include \
+ $(libprocess_la_CPPFLAGS)
+
+tests_LDADD = 3rdparty/libgmock.la libprocess.la
+
+TESTS = tests
+
+# TODO(benh): Fix shared builds (tests need libglog, libev, etc).
+
+# Using LT_OUTPUT in configure.ac creates config.lt that doesn't get
+# cleaned up by distclean-libtool. See this bug patch (which doesn't
+# appear to be in all versions of libtool.m4):
+# http://lists.gnu.org/archive/html/automake-commit/2008-11/msg00015.html.
+distclean-local:
+ -rm -f config.lt
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/README
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/README b/3rdparty/libprocess/README
new file mode 100644
index 0000000..89b009f
--- /dev/null
+++ b/3rdparty/libprocess/README
@@ -0,0 +1,10 @@
+README for libprocess
+
+Most importantly, if you run into an issue, please send me an email:
+benh@berkeley.edu.
+
+$ ./bootstrap # Unless you already have a distribution.
+$ mkdir build && cd build # Optional.
+$ path/to/configure
+$ make
+$ make check
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/TODO
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/TODO b/3rdparty/libprocess/TODO
new file mode 100644
index 0000000..9770546
--- /dev/null
+++ b/3rdparty/libprocess/TODO
@@ -0,0 +1,33 @@
+/* TODO(benh): Improve link/connection management. For example, make
+ links be about sockets. Then see whether or not already connected
+ sockets can be used for sending a message back (without opening a
+ new socket first). */
+
+/* TODO(benh): When a link fails, try and reconnect a configurable
+ number of times before you just assume the link is dead. */
+
+/* TODO(benh): Fix link functionality (processes need to send
+ process_exit message since a dead process on one node might not
+ know that a process on another node linked with it). */
+
+/* TODO(benh): What happens when a remote link exits? Do we close the
+ socket correclty?. */
+
+/* TODO(benh): Handle/Enable forking. */
+
+/* TODO(benh): Use multiple processing threads (do process affinity). */
+
+/* TODO(benh): Better error handling (i.e., warn if re-spawn process
+ instead of just returning bad pid). */
+
+/* TODO(benh): Use different backends for files and sockets. */
+
+/* TODO(benh): Allow messages to be received out-of-order (i.e., allow
+ someone to do a receive with a message id and let other messages
+ queue until a message with that message id is received). */
+
+/* TODO(benh): LinkManager::link and LinkManager::send are pretty big
+ functions, we could probably create some queue that the I/O thread
+ checks for sending messages and creating links instead ... that
+ would probably be faster, and have less contention for the mutex
+ (that might mean we can eliminate contention for the mutex!). */
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/bootstrap
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/bootstrap b/3rdparty/libprocess/bootstrap
new file mode 100755
index 0000000..1d3215d
--- /dev/null
+++ b/3rdparty/libprocess/bootstrap
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Make sure that we are in the right directory.
+if test ! -f configure.ac; then
+ cat >&2 <<__EOF__
+You must run bootstrap from the root of the distribution.
+__EOF__
+ exit 1
+fi
+
+autoreconf --install -Wall --verbose "${@}"
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/configure.ac
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/configure.ac b/3rdparty/libprocess/configure.ac
new file mode 100644
index 0000000..d3b86a3
--- /dev/null
+++ b/3rdparty/libprocess/configure.ac
@@ -0,0 +1,117 @@
+# Generated with autoscan, then modified appropriately.
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.61])
+AC_INIT([libprocess], [0.0.1])
+
+# Have autoconf setup some variables related to the system.
+AC_CANONICAL_HOST
+AC_CANONICAL_BUILD
+AC_CANONICAL_TARGET
+
+AC_LANG([C++])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+# Initialize automake.
+# -Wno-portability, since we require GNU Make for % patterns.
+AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability foreign])
+
+# Required for linking non-POSIX libs.
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+
+# Initialize libtool (LT_OUTPUT builds ./libtool immediately, needed
+# if we want to do tests with libtool during configuration).
+LT_PREREQ([2.2])
+LT_INIT
+LT_LANG([C++])
+LT_OUTPUT
+
+# The default CFLAGS/CXXFLAGS from autoconf when using gcc usually
+# includes "-O2". These really slow down compiling our tests, so we
+# turn them off and enable them (where desired) directly in the
+# Makefile. Note that this should not have an impact on users setting
+# CFLAGS/CXXFLAGS directly at configure time, or when running make.
+AS_IF([test "x${ac_cv_env_CFLAGS_set}" = "x"], [CFLAGS="-g"])
+AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"], [CXXFLAGS="-g"])
+
+# Save the configure arguments so we can pass them to any third-party
+# libraries that we might run configure on (see
+# 3rdparty/Makefile.am). One downside of our strategy for shipping
+# and building third-party libraries is that we can't expose options
+# from nested third-party configure scripts.
+CONFIGURE_ARGS="$ac_configure_args"
+AC_SUBST(CONFIGURE_ARGS)
+
+AC_CONFIG_SUBDIRS([3rdparty/stout])
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([3rdparty/Makefile])
+
+AC_ARG_ENABLE([install],
+ AS_HELP_STRING([--enable-install],
+ [install libprocess]),
+ [AC_MSG_ERROR([libprocess can not currently be installed])])
+
+AC_ARG_ENABLE([optimize],
+ AS_HELP_STRING([--disable-optimize],
+ [don't try to compile with optimizations]),
+ [], [enable_optimize=yes])
+
+AC_ARG_ENABLE([perftools],
+ AS_HELP_STRING([--enable-perftools],
+ [enable google perftools]),
+ [gperftools=yes])
+
+AC_ARG_WITH([zlib],
+ AS_HELP_STRING([--without-zlib],
+ [disables zlib compression, which means the webui
+ will be far less responsive; not recommended]),
+ [], [with_zlib=yes])
+
+# Do some OS specific setup.
+case "${target_os}" in
+ linux*)
+ LIBS="$LIBS -lrt" # For clock_gettime() in stout/stopwatch.hpp.
+ OS_NAME=linux # Used below for OS_LINUX.
+ ;;
+ *)
+ ;;
+esac
+
+# Checks for gcc toolchain (we rely on some atomic builtins for now).
+AC_PROG_CXX([g++])
+AC_PROG_CC([gcc])
+
+# Check for pthreads (uses m4/acx_pthread.m4).
+ACX_PTHREAD([], [AC_MSG_ERROR([failed to find pthreads])])
+
+
+# Check if we should try and enable optimizations.
+if test "x$enable_optimize" = "xyes"; then
+ # For now, we only turn on optimizations for gcc.
+ if test "x$GCC" = "xyes"; then
+ CXXFLAGS="$CXXFLAGS -g2 -O2"
+ fi
+fi
+
+
+# Check if we should/can build with libz.
+if test "x$with_zlib" = "xyes"; then
+ AC_CHECK_LIB([z], [deflate, gzread, gzwrite, inflate], [],
+ [AC_MSG_ERROR([cannot find libz
+ -------------------------------------------------------------------
+ This means HTTP responses will be slower because we cannot use
+ compression; you probably want to download and install zlib, but
+ you can get away without it by doing --without-zlib.
+ -------------------------------------------------------------------
+ ])])
+fi
+
+AM_CONDITIONAL([HAS_GPERFTOOLS], [test "x$gperftools" = "xyes"])
+
+# Used for conditionally building source files (e.g., only want to
+# build stout/tests/proc_tests.cpp on Linux).
+AM_CONDITIONAL([OS_LINUX], [test "x$OS_NAME" = "xlinux"])
+
+AC_OUTPUT
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/examples/example.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/examples/example.cpp b/3rdparty/libprocess/examples/example.cpp
new file mode 100644
index 0000000..3fb4ef5
--- /dev/null
+++ b/3rdparty/libprocess/examples/example.cpp
@@ -0,0 +1,121 @@
+#include <iostream>
+#include <sstream>
+
+#include <process/defer.hpp>
+#include <process/dispatch.hpp>
+#include <process/future.hpp>
+#include <process/http.hpp>
+#include <process/process.hpp>
+
+using namespace process;
+
+using namespace process::http;
+
+using std::string;
+
+class MyProcess : public Process<MyProcess>
+{
+public:
+ MyProcess() {}
+ virtual ~MyProcess() {}
+
+ Future<int> func1()
+ {
+ promise.future().onAny(
+ defer([=] (const Future<int>& future) {
+ terminate(self());
+ }));
+ return promise.future();
+ }
+
+ void func2(int i)
+ {
+ promise.set(i);
+ }
+
+ Future<Response> vars(const Request& request)
+ {
+ string body = "... vars here ...";
+ OK response;
+ response.headers["Content-Type"] = "text/plain";
+ std::ostringstream out;
+ out << body.size();
+ response.headers["Content-Length"] = out.str();
+ response.body = body;
+ return response;
+ }
+
+ void stop(const UPID& from, const string& body)
+ {
+ terminate(self());
+ }
+
+protected:
+ virtual void initialize()
+ {
+// route("/vars", &MyProcess::vars);
+ route("/vars", [=] (const Request& request) {
+ string body = "... vars here ...";
+ OK response;
+ response.headers["Content-Type"] = "text/plain";
+ std::ostringstream out;
+ out << body.size();
+ response.headers["Content-Length"] = out.str();
+ response.body = body;
+ return response;
+ });
+
+// install("stop", &MyProcess::stop);
+ install("stop", [=] (const UPID& from, const string& body) {
+ terminate(self());
+ });
+ }
+
+private:
+ Promise<int> promise;
+};
+
+
+int main(int argc, char** argv)
+{
+ MyProcess process;
+ PID<MyProcess> pid = spawn(&process);
+
+ PID<> pid2 = pid;
+
+// --------------------------------------
+
+// Future<int> future = dispatch(pid, &MyProcess::func1);
+// dispatch(pid, &MyProcess::func2, 42);
+
+// std::cout << future.get() << std::endl;
+
+// post(pid, "stop");
+
+// --------------------------------------
+
+// Promise<bool> p;
+
+// dispatch(pid, &MyProcess::func1)
+// .then([=, &p] (int i) {
+// p.set(i == 42);
+// return p.future();
+// })
+// .then([=] (bool b) {
+// if (b) {
+// post(pid, "stop");
+// }
+// return true; // No Future<void>.
+// });
+
+// dispatch(pid, &MyProcess::func2, 42);
+
+// --------------------------------------
+
+ dispatch(pid, &MyProcess::func1);
+ dispatch(pid, &MyProcess::func2, 42);
+
+
+ wait(pid);
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/include/process/async.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/async.hpp b/3rdparty/libprocess/include/process/async.hpp
new file mode 100644
index 0000000..8fa2771
--- /dev/null
+++ b/3rdparty/libprocess/include/process/async.hpp
@@ -0,0 +1,231 @@
+#ifndef __ASYNC_HPP__
+#define __ASYNC_HPP__
+
+#include <process/dispatch.hpp>
+#include <process/future.hpp>
+#include <process/id.hpp>
+#include <process/process.hpp>
+
+#include <tr1/functional>
+
+namespace process {
+
+// TODO(vinod): Merge this into ExecutorProcess.
+// TODO(vinod): Add support for void functions. Currently this is tricky,
+// because Future<void> is not supported.
+class AsyncExecutorProcess : public Process<AsyncExecutorProcess>
+{
+private:
+ friend class AsyncExecutor;
+
+ AsyncExecutorProcess() : ProcessBase(ID::generate("__async_executor__")) {}
+ virtual ~AsyncExecutorProcess() {}
+
+ // Not copyable, not assignable.
+ AsyncExecutorProcess(const AsyncExecutorProcess&);
+ AsyncExecutorProcess& operator = (const AsyncExecutorProcess&);
+
+ template<typename F>
+ typename std::tr1::result_of<F(void)>::type execute(
+ const F& f)
+ {
+ terminate(self()); // Terminate this process after the function returns.
+ return f();
+ }
+
+ // TODO(vinod): Use boost macro enumerations.
+ template<typename F, typename A1>
+ typename std::tr1::result_of<F(A1)>::type execute(
+ const F& f, A1 a1)
+ {
+ terminate(self()); // Terminate this process after the function returns.
+ return f(a1);
+ }
+
+ template<typename F, typename A1, typename A2>
+ typename std::tr1::result_of<F(A1, A2)>::type execute(
+ const F& f, A1 a1, A2 a2)
+ {
+ terminate(self()); // Terminate this process after the function returns.
+ return f(a1, a2);
+ }
+
+ template<typename F, typename A1, typename A2, typename A3>
+ typename std::tr1::result_of<F(A1, A2, A3)>::type execute(
+ const F& f, A1 a1, A2 a2, A3 a3)
+ {
+ terminate(self()); // Terminate this process after the function returns.
+ return f(a1, a2, a3);
+ }
+
+ template<typename F, typename A1, typename A2, typename A3, typename A4>
+ typename std::tr1::result_of<F(A1, A2, A3, A4)>::type execute(
+ const F& f, A1 a1, A2 a2, A3 a3, A4 a4)
+ {
+ terminate(self()); // Terminate this process after the function returns.
+ return f(a1, a2, a3, a4);
+ }
+};
+
+
+// This is a wrapper around AsyncExecutorProcess.
+class AsyncExecutor
+{
+private:
+ // Declare async functions as friends.
+ template<typename F>
+ friend Future<typename std::tr1::result_of<F(void)>::type> async(
+ const F& f);
+
+ template<typename F, typename A1>
+ friend Future<typename std::tr1::result_of<F(A1)>::type> async(
+ const F& f, A1 a1);
+
+ template<typename F, typename A1, typename A2>
+ friend Future<typename std::tr1::result_of<F(A1, A2)>::type> async(
+ const F& f, A1 a1, A2 a2);
+
+ template<typename F, typename A1, typename A2, typename A3>
+ friend Future<typename std::tr1::result_of<F(A1, A2, A3)>::type> async(
+ const F& f, A1 a1, A2 a2, A3 a3);
+
+ template<typename F, typename A1, typename A2, typename A3, typename A4>
+ friend Future<typename std::tr1::result_of<F(A1, A2, A3, A4)>::type> async(
+ const F& f, A1 a1, A2 a2, A3 a3, A4 a4);
+
+ AsyncExecutor()
+ {
+ process = new AsyncExecutorProcess();
+ spawn(process, true); // Automatically GC.
+ }
+
+ virtual ~AsyncExecutor() {}
+
+ // Not copyable, not assignable.
+ AsyncExecutor(const AsyncExecutor&);
+ AsyncExecutor& operator = (const AsyncExecutor&);
+
+ template<typename F>
+ Future<typename std::tr1::result_of<F(void)>::type> execute(
+ const F& f)
+ {
+ // Necessary to disambiguate.
+ typedef typename std::tr1::result_of<F(void)>::type
+ (AsyncExecutorProcess::*R)(const F&);
+
+ return dispatch(process,
+ static_cast<R>(&AsyncExecutorProcess::execute),
+ f);
+ }
+
+ // TODO(vinod): Use boost macro enumerations.
+ template<typename F, typename A1>
+ Future<typename std::tr1::result_of<F(A1)>::type> execute(
+ const F& f, A1 a1)
+ {
+ // Necessary to disambiguate.
+ typedef typename std::tr1::result_of<F(A1)>::type
+ (AsyncExecutorProcess::*R)(const F&, A1);
+
+ return dispatch(process,
+ static_cast<R>(&AsyncExecutorProcess::execute),
+ f,
+ a1);
+ }
+
+ template<typename F, typename A1, typename A2>
+ Future<typename std::tr1::result_of<F(A1, A2)>::type> execute(
+ const F& f, A1 a1, A2 a2)
+ {
+ // Necessary to disambiguate.
+ typedef typename std::tr1::result_of<F(A1, A2)>::type
+ (AsyncExecutorProcess::*R)(const F&, A1, A2);
+
+ return dispatch(process,
+ static_cast<R>(&AsyncExecutorProcess::execute),
+ f,
+ a1,
+ a2);
+ }
+
+ template<typename F, typename A1, typename A2, typename A3>
+ Future<typename std::tr1::result_of<F(A1, A2, A3)>::type> execute(
+ const F& f, A1 a1, A2 a2, A3 a3)
+ {
+ // Necessary to disambiguate.
+ typedef typename std::tr1::result_of<F(A1, A2, A3)>::type
+ (AsyncExecutorProcess::*R)(const F&, A1, A2, A3);
+
+ return dispatch(process,
+ static_cast<R>(&AsyncExecutorProcess::execute),
+ f,
+ a1,
+ a2,
+ a3);
+ }
+
+ template<typename F, typename A1, typename A2, typename A3, typename A4>
+ Future<typename std::tr1::result_of<F(A1, A2, A3, A4)>::type> execute(
+ const F& f, A1 a1, A2 a2, A3 a3, A4 a4)
+ {
+ // Necessary to disambiguate.
+ typedef typename std::tr1::result_of<F(A1, A2, A3, A4)>::type
+ (AsyncExecutorProcess::*R)(const F&, A1, A2, A3, A4);
+
+ return dispatch(process,
+ static_cast<R>(&AsyncExecutorProcess::execute),
+ f,
+ a1,
+ a2,
+ a3,
+ a4);
+ }
+
+ AsyncExecutorProcess* process;
+};
+
+
+// Provides an abstraction for asynchronously executing a function.
+// TODO(vinod): Use boost macro to enumerate arguments/params.
+template<typename F>
+Future<typename std::tr1::result_of<F(void)>::type>
+ async(const F& f)
+{
+ return AsyncExecutor().execute(f);
+}
+
+
+template<typename F, typename A1>
+Future<typename std::tr1::result_of<F(A1)>::type>
+ async(const F& f, A1 a1)
+{
+ return AsyncExecutor().execute(f, a1);
+}
+
+
+template<typename F, typename A1, typename A2>
+Future<typename std::tr1::result_of<F(A1, A2)>::type>
+ async(const F& f, A1 a1, A2 a2)
+{
+ return AsyncExecutor().execute(f, a1, a2);
+}
+
+
+template<typename F, typename A1, typename A2, typename A3>
+Future<typename std::tr1::result_of<F(A1, A2, A3)>::type>
+ async(const F& f, A1 a1, A2 a2, A3 a3)
+{
+ return AsyncExecutor().execute(f, a1, a2, a3);
+}
+
+
+template<typename F, typename A1, typename A2, typename A3, typename A4>
+Future<typename std::tr1::result_of<F(A1, A2, A3, A4)>::type>
+ async(const F& f, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ return AsyncExecutor().execute(f, a1, a2, a3, a4);
+}
+
+} // namespace process {
+
+#endif // __ASYNC_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/include/process/clock.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/clock.hpp b/3rdparty/libprocess/include/process/clock.hpp
new file mode 100644
index 0000000..82ae3c6
--- /dev/null
+++ b/3rdparty/libprocess/include/process/clock.hpp
@@ -0,0 +1,32 @@
+#ifndef __PROCESS_CLOCK_HPP__
+#define __PROCESS_CLOCK_HPP__
+
+#include <process/time.hpp>
+
+#include <stout/duration.hpp>
+
+namespace process {
+
+// Forward declarations.
+class ProcessBase;
+class Time;
+
+class Clock
+{
+public:
+ static Time now();
+ static Time now(ProcessBase* process);
+ static void pause();
+ static bool paused();
+ static void resume();
+ static void advance(const Duration& duration);
+ static void advance(ProcessBase* process, const Duration& duration);
+ static void update(const Time& time);
+ static void update(ProcessBase* process, const Time& time);
+ static void order(ProcessBase* from, ProcessBase* to);
+ static void settle();
+};
+
+} // namespace process {
+
+#endif // __PROCESS_CLOCK_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/include/process/collect.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/collect.hpp b/3rdparty/libprocess/include/process/collect.hpp
new file mode 100644
index 0000000..8050351
--- /dev/null
+++ b/3rdparty/libprocess/include/process/collect.hpp
@@ -0,0 +1,125 @@
+#ifndef __PROCESS_COLLECT_HPP__
+#define __PROCESS_COLLECT_HPP__
+
+#include <assert.h>
+
+#include <list>
+
+#include <process/defer.hpp>
+#include <process/delay.hpp>
+#include <process/future.hpp>
+#include <process/process.hpp>
+#include <process/timeout.hpp>
+
+#include <stout/none.hpp>
+#include <stout/option.hpp>
+
+namespace process {
+
+// Waits on each future in the specified set and returns the set of
+// resulting values. If any future is discarded then the result will
+// be a failure. Likewise, if any future fails than the result future
+// will be a failure.
+template <typename T>
+Future<std::list<T> > collect(
+ std::list<Future<T> >& futures,
+ const Option<Timeout>& timeout = None());
+
+
+namespace internal {
+
+template <typename T>
+class CollectProcess : public Process<CollectProcess<T> >
+{
+public:
+ CollectProcess(
+ const std::list<Future<T> >& _futures,
+ const Option<Timeout>& _timeout,
+ Promise<std::list<T> >* _promise)
+ : futures(_futures),
+ timeout(_timeout),
+ promise(_promise) {}
+
+ virtual ~CollectProcess()
+ {
+ delete promise;
+ }
+
+ virtual void initialize()
+ {
+ // Stop this nonsense if nobody cares.
+ promise->future().onDiscarded(defer(this, &CollectProcess::discarded));
+
+ // Only wait as long as requested.
+ if (timeout.isSome()) {
+ delay(timeout.get().remaining(), this, &CollectProcess::timedout);
+ }
+
+ typename std::list<Future<T> >::const_iterator iterator;
+ for (iterator = futures.begin(); iterator != futures.end(); ++iterator) {
+ (*iterator).onAny(
+ defer(this, &CollectProcess::waited, std::tr1::placeholders::_1));
+ }
+ }
+
+private:
+ void discarded()
+ {
+ terminate(this);
+ }
+
+ void timedout()
+ {
+ // Need to discard all of the futures so any of their associated
+ // resources can get properly cleaned up.
+ typename std::list<Future<T> >::const_iterator iterator;
+ for (iterator = futures.begin(); iterator != futures.end(); ++iterator) {
+ Future<T> future = *iterator; // Need a non-const copy to discard.
+ future.discard();
+ }
+
+ promise->fail("Collect failed: timed out");
+ terminate(this);
+ }
+
+ void waited(const Future<T>& future)
+ {
+ if (future.isFailed()) {
+ promise->fail("Collect failed: " + future.failure());
+ terminate(this);
+ } else if (future.isDiscarded()) {
+ promise->fail("Collect failed: future discarded");
+ terminate(this);
+ } else {
+ assert(future.isReady());
+ values.push_back(future.get());
+ if (futures.size() == values.size()) {
+ promise->set(values);
+ terminate(this);
+ }
+ }
+ }
+
+ const std::list<Future<T> > futures;
+ const Option<Timeout> timeout;
+ Promise<std::list<T> >* promise;
+ std::list<T> values;
+};
+
+} // namespace internal {
+
+
+template <typename T>
+inline Future<std::list<T> > collect(
+ std::list<Future<T> >& futures,
+ const Option<Timeout>& timeout)
+{
+ Promise<std::list<T> >* promise = new Promise<std::list<T> >();
+ Future<std::list<T> > future = promise->future();
+ spawn(new internal::CollectProcess<T>(futures, timeout, promise), true);
+ return future;
+}
+
+} // namespace process {
+
+#endif // __PROCESS_COLLECT_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/include/process/defer.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/defer.hpp b/3rdparty/libprocess/include/process/defer.hpp
new file mode 100644
index 0000000..1eb770b
--- /dev/null
+++ b/3rdparty/libprocess/include/process/defer.hpp
@@ -0,0 +1,438 @@
+#ifndef __PROCESS_DEFER_HPP__
+#define __PROCESS_DEFER_HPP__
+
+#include <tr1/functional>
+
+#include <process/deferred.hpp>
+#include <process/dispatch.hpp>
+#include <process/executor.hpp>
+
+#include <stout/preprocessor.hpp>
+
+namespace process {
+
+// The defer mechanism is very similar to the dispatch mechanism (see
+// dispatch.hpp), however, rather than scheduling the method to get
+// invoked, the defer mechanism returns a 'Deferred' object that when
+// invoked does the underlying dispatch. Similar to dispatch, we
+// provide the C++11 variadic template definitions first, and then use
+// Boost preprocessor macros to provide the actual definitions.
+
+
+// First, definitions of defer for methods returning void:
+//
+// template <typename T, typename ...P>
+// Deferred<void(void)> void defer(const PID<T>& pid,
+// void (T::*method)(P...),
+// P... p)
+// {
+// void (*dispatch)(const PID<T>&, void (T::*)(P...), P...) =
+// &process::template dispatch<T, P...>;
+
+// return Deferred<void(void)>(
+// std::tr1::bind(dispatch, pid, method, std::forward<P>(p)...));
+// }
+
+template <typename T>
+_Defer<void(*(PID<T>, void (T::*)(void)))
+ (const PID<T>&, void (T::*)(void))>
+defer(const PID<T>& pid, void (T::*method)(void))
+{
+ void (*dispatch)(const PID<T>&, void (T::*)(void)) =
+ &process::template dispatch<T>;
+ return std::tr1::bind(dispatch, pid, method);
+}
+
+template <typename T>
+_Defer<void(*(PID<T>, void (T::*)(void)))
+ (const PID<T>&, void (T::*)(void))>
+defer(const Process<T>& process, void (T::*method)(void))
+{
+ return defer(process.self(), method);
+}
+
+template <typename T>
+_Defer<void(*(PID<T>, void (T::*)(void)))
+ (const PID<T>&, void (T::*)(void))>
+defer(const Process<T>* process, void (T::*method)(void))
+{
+ return defer(process->self(), method);
+}
+
+#define TEMPLATE(Z, N, DATA) \
+ template <typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<void(*(PID<T>, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const PID<T>& pid, \
+ void (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ void (*dispatch)(const PID<T>&, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P)) = \
+ &process::template dispatch<T, ENUM_PARAMS(N, P), ENUM_PARAMS(N, P)>; \
+ return std::tr1::bind(dispatch, pid, method, ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<void(*(PID<T>, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const Process<T>& process, \
+ void (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ return defer(process.self(), method, ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<void(*(PID<T>, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const Process<T>* process, \
+ void (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ return defer(process->self(), method, ENUM_PARAMS(N, a)); \
+ }
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+
+// Next, definitions of defer for methods returning future:
+//
+// template <typename R, typename T, typename ...P>
+// Deferred<Future<R>(void)> void defer(const PID<T>& pid,
+// Future<R> (T::*method)(P...),
+// P... p)
+// {
+// Future<R> (*dispatch)(const PID<T>&, Future<R> (T::*)(P...), P...) =
+// &process::template dispatch<R, T, P...>;
+//
+// return Deferred<Future<R>(void)>(
+// std::tr1::bind(dispatch, pid, method, std::forward<P>(p)...));
+// }
+
+template <typename R, typename T>
+_Defer<Future<R>(*(PID<T>, Future<R> (T::*)(void)))
+ (const PID<T>&, Future<R> (T::*)(void))>
+defer(const PID<T>& pid, Future<R> (T::*method)(void))
+{
+ Future<R> (*dispatch)(const PID<T>&, Future<R> (T::*)(void)) =
+ &process::template dispatch<R, T>;
+ return std::tr1::bind(dispatch, pid, method);
+}
+
+template <typename R, typename T>
+_Defer<Future<R>(*(PID<T>, Future<R> (T::*)(void)))(
+ const PID<T>&, Future<R> (T::*)(void))>
+defer(const Process<T>& process, Future<R> (T::*method)(void))
+{
+ return defer(process.self(), method);
+}
+
+template <typename R, typename T>
+_Defer<Future<R>(*(PID<T>, Future<R> (T::*)(void)))
+ (const PID<T>&, Future<R> (T::*)(void))>
+defer(const Process<T>* process, Future<R> (T::*method)(void))
+{
+ return defer(process->self(), method);
+}
+
+#define TEMPLATE(Z, N, DATA) \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<Future<R>(*(PID<T>, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const PID<T>& pid, \
+ Future<R> (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ Future<R> (*dispatch)(const PID<T>&, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P)) = \
+ &process::template dispatch<R, T, ENUM_PARAMS(N, P), ENUM_PARAMS(N, P)>; \
+ return std::tr1::bind(dispatch, pid, method, ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<Future<R>(*(PID<T>, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const Process<T>& process, \
+ Future<R> (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ return defer(process.self(), method, ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<Future<R>(*(PID<T>, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const Process<T>* process, \
+ Future<R> (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ return defer(process->self(), method, ENUM_PARAMS(N, a)); \
+ }
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+
+// Next, definitions of defer for methods returning a value:
+//
+// template <typename R, typename T, typename ...P>
+// Deferred<Future<R>(void)> void defer(const PID<T>& pid,
+// R (T::*method)(P...),
+// P... p)
+// {
+// Future<R> (*dispatch)(const PID<T>&, R (T::*)(P...), P...) =
+// &process::template dispatch<R, T, P...>;
+//
+// return Deferred<Future<R>(void)>(
+// std::tr1::bind(dispatch, pid, method, std::forward<P>(p)...));
+// }
+
+template <typename R, typename T>
+_Defer<Future<R>(*(PID<T>, R (T::*)(void)))
+ (const PID<T>&, R (T::*)(void))>
+defer(const PID<T>& pid, R (T::*method)(void))
+{
+ Future<R> (*dispatch)(const PID<T>&, R (T::*)(void)) =
+ &process::template dispatch<R, T>;
+ return std::tr1::bind(dispatch, pid, method);
+}
+
+template <typename R, typename T>
+_Defer<Future<R>(*(PID<T>, R (T::*)(void)))
+ (const PID<T>&, R (T::*)(void))>
+defer(const Process<T>& process, R (T::*method)(void))
+{
+ return defer(process.self(), method);
+}
+
+template <typename R, typename T>
+_Defer<Future<R>(*(PID<T>, R (T::*)(void)))
+ (const PID<T>&, R (T::*)(void))>
+defer(const Process<T>* process, R (T::*method)(void))
+{
+ return defer(process->self(), method);
+}
+
+#define TEMPLATE(Z, N, DATA) \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<Future<R>(*(PID<T>, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const PID<T>& pid, \
+ R (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ Future<R> (*dispatch)(const PID<T>&, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P)) = \
+ &process::template dispatch<R, T, ENUM_PARAMS(N, P), ENUM_PARAMS(N, P)>; \
+ return std::tr1::bind(dispatch, pid, method, ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<Future<R>(*(PID<T>, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const Process<T>& process, \
+ R (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ return defer(process.self(), method, ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ _Defer<Future<R>(*(PID<T>, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const Process<T>* process, \
+ R (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ return defer(process->self(), method, ENUM_PARAMS(N, a)); \
+ }
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+
+namespace internal {
+
+inline void invoker(
+ ProcessBase* _,
+ const std::tr1::function<void(void)>& f)
+{
+ f();
+}
+
+inline void dispatcher(
+ const UPID& pid,
+ const std::tr1::function<void(void)>& f)
+{
+ std::tr1::shared_ptr<std::tr1::function<void(ProcessBase*)> > invoker(
+ new std::tr1::function<void(ProcessBase*)>(
+ std::tr1::bind(&internal::invoker,
+ std::tr1::placeholders::_1,
+ f)));
+
+ internal::dispatch(pid, invoker);
+}
+
+#define TEMPLATE(Z, N, DATA) \
+ template <ENUM_PARAMS(N, typename A)> \
+ void CAT(invoker, N)( \
+ ProcessBase* _, \
+ const std::tr1::function<void(ENUM_PARAMS(N, A))>& f, \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ f(ENUM_PARAMS(N, a)); \
+ } \
+ \
+ template <ENUM_PARAMS(N, typename A)> \
+ void CAT(dispatcher, N)( \
+ const UPID& pid, \
+ const std::tr1::function<void(ENUM_PARAMS(N, A))>& f, \
+ ENUM_BINARY_PARAMS(N, A, a)) \
+ { \
+ std::tr1::shared_ptr<std::tr1::function<void(ProcessBase*)> > invoker( \
+ new std::tr1::function<void(ProcessBase*)>( \
+ std::tr1::bind(&internal::CAT(invoker, N)<ENUM_PARAMS(N, A)>, \
+ std::tr1::placeholders::_1, \
+ f, \
+ ENUM_PARAMS(N, a)))); \
+ \
+ internal::dispatch(pid, invoker); \
+ }
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+
+ // We can't easily use 'std::tr1::_Placeholder<X>' when doing macro
+ // expansion via ENUM_BINARY_PARAMS because compilers don't like it
+ // when you try and concatenate '<' 'N' '>'. Thus, we typedef them.
+#define TEMPLATE(Z, N, DATA) \
+ typedef std::tr1::_Placeholder<INC(N)> _ ## N;
+
+ REPEAT(10, TEMPLATE, _)
+#undef TEMPLATE
+
+} // namespace internal {
+
+
+// Now we define defer calls for functions and bind statements.
+inline Deferred<void(void)> defer(const std::tr1::function<void(void)>& f)
+{
+ if (__process__ != NULL) {
+ // In C++11:
+ // const UPID pid = __process__->self();
+ // return []() {
+ // internal::dispatch(pid, [](ProcessBase* _) { f(); });
+ // }
+ return std::tr1::function<void(void)>(
+ std::tr1::bind(&internal::dispatcher,
+ __process__->self(),
+ f));
+ }
+
+ return __executor__->defer(f);
+}
+
+
+#define TEMPLATE(Z, N, DATA) \
+ template <ENUM_PARAMS(N, typename A)> \
+ Deferred<void(ENUM_PARAMS(N, A))> defer( \
+ const std::tr1::function<void(ENUM_PARAMS(N, A))>& f) \
+ { \
+ if (__process__ != NULL) { \
+ return std::tr1::function<void(ENUM_PARAMS(N, A))>( \
+ std::tr1::bind(&internal::CAT(dispatcher, N)<ENUM_PARAMS(N, A)>, \
+ __process__->self(), \
+ f, \
+ ENUM_BINARY_PARAMS(N, internal::_, () INTERCEPT))); \
+ } \
+ \
+ return __executor__->defer(f); \
+ } \
+ \
+ template <typename R, ENUM_PARAMS(N, typename A)> \
+ Deferred<Future<R>(ENUM_PARAMS(N, A))> defer( \
+ const std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>& f) \
+ { \
+ if (__process__ != NULL) { \
+ return std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>( \
+ std::tr1::bind(&internal::CAT(dispatcher, N)<ENUM_PARAMS(N, A)>, \
+ __process__->self(), \
+ f, \
+ ENUM_BINARY_PARAMS(N, internal::_, () INTERCEPT))); \
+ } \
+ \
+ return __executor__->defer(f); \
+ }
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+} // namespace process {
+
+#endif // __PROCESS_DEFER_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/71a01bd9/3rdparty/libprocess/include/process/deferred.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/deferred.hpp b/3rdparty/libprocess/include/process/deferred.hpp
new file mode 100644
index 0000000..8907e80
--- /dev/null
+++ b/3rdparty/libprocess/include/process/deferred.hpp
@@ -0,0 +1,136 @@
+#ifndef __PROCESS_DEFERRED_HPP__
+#define __PROCESS_DEFERRED_HPP__
+
+#include <tr1/functional>
+
+#include <process/future.hpp>
+#include <process/pid.hpp>
+
+#include <stout/preprocessor.hpp>
+
+namespace process {
+
+// Forward declarations (removing these produces cryptic compiler
+// errors even though we are just using them to declare friends).
+class Executor;
+template <typename _F> struct _Defer;
+
+
+// Acts like a function call but runs within an asynchronous execution
+// context such as an Executor or a ProcessBase (enforced because only
+// an executor or the 'defer' routines are allowed to create them).
+template <typename F>
+struct Deferred : std::tr1::function<F>
+{
+private:
+ // Only an Executor and the 'defer' routines can create these.
+ friend class Executor;
+
+ template <typename _F> friend struct _Defer;
+
+ friend Deferred<void(void)> defer(const std::tr1::function<void(void)>& f);
+
+#define TEMPLATE(Z, N, DATA) \
+ template <ENUM_PARAMS(N, typename A)> \
+ friend Deferred<void(ENUM_PARAMS(N, A))> defer( \
+ const std::tr1::function<void(ENUM_PARAMS(N, A))>& f);
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+ Deferred(const std::tr1::function<F>& f) : std::tr1::function<F>(f) {}
+};
+
+
+// The result of invoking the 'defer' routines is actually an internal
+// type, effectively just a wrapper around the result of invoking
+// 'std::tr1::bind'. However, we want the result of bind to be
+// castable to a 'Deferred' but we don't want anyone to be able to
+// create a 'Deferred' so we use a level-of-indirection via this type.
+template <typename F>
+struct _Defer : std::tr1::_Bind<F>
+{
+ template <typename _F>
+ operator Deferred<_F> ()
+ {
+ return Deferred<_F>(std::tr1::function<_F>(*this));
+ }
+
+private:
+ friend class Executor;
+
+ template <typename T>
+ friend _Defer<void(*(PID<T>, void (T::*)(void)))
+ (const PID<T>&, void (T::*)(void))>
+ defer(const PID<T>& pid, void (T::*method)(void));
+
+#define TEMPLATE(Z, N, DATA) \
+ template <typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ friend _Defer<void(*(PID<T>, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ void (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const PID<T>& pid, \
+ void (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a));
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+ template <typename R, typename T>
+ friend _Defer<Future<R>(*(PID<T>, Future<R> (T::*)(void)))(
+ const PID<T>&, Future<R> (T::*)(void))>
+ defer(const PID<T>& pid, Future<R> (T::*method)(void));
+
+#define TEMPLATE(Z, N, DATA) \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ friend _Defer<Future<R>(*(PID<T>, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ Future<R> (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const PID<T>& pid, \
+ Future<R> (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a));
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+ template <typename R, typename T>
+ friend _Defer<Future<R>(*(PID<T>, R (T::*)(void)))(
+ const PID<T>&, R (T::*)(void))>
+ defer(const PID<T>& pid, R (T::*method)(void));
+
+#define TEMPLATE(Z, N, DATA) \
+ template <typename R, \
+ typename T, \
+ ENUM_PARAMS(N, typename P), \
+ ENUM_PARAMS(N, typename A)> \
+ friend _Defer<Future<R>(*(PID<T>, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, A))) \
+ (const PID<T>&, \
+ R (T::*)(ENUM_PARAMS(N, P)), \
+ ENUM_PARAMS(N, P))> \
+ defer(const PID<T>& pid, \
+ R (T::*method)(ENUM_PARAMS(N, P)), \
+ ENUM_BINARY_PARAMS(N, A, a));
+
+ REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.
+#undef TEMPLATE
+
+ _Defer(const std::tr1::_Bind<F>& b)
+ : std::tr1::_Bind<F>(b) {}
+};
+
+} // namespace process {
+
+#endif // __PROCESS_DEFERRED_HPP__