Commit 60145838 authored by Kenton Varda's avatar Kenton Varda

Merge pull request #331 from harrishancock/vs2015-capnp-lite

Re-enable MSVC lite-mode
parents 44d91b41 0c641ecf
...@@ -247,6 +247,8 @@ TEST(Any, AnyStructListCapInSchema) { ...@@ -247,6 +247,8 @@ TEST(Any, AnyStructListCapInSchema) {
checkList(anyList.as<List<int>>(), {123, 456, 789}); checkList(anyList.as<List<int>>(), {123, 456, 789});
} }
#if !CAPNP_LITE
// This portion of the test relies on a Client, not present in lite-mode.
{ {
kj::EventLoop loop; kj::EventLoop loop;
kj::WaitScope waitScope(loop); kj::WaitScope waitScope(loop);
...@@ -259,6 +261,7 @@ TEST(Any, AnyStructListCapInSchema) { ...@@ -259,6 +261,7 @@ TEST(Any, AnyStructListCapInSchema) {
req.send().wait(waitScope); req.send().wait(waitScope);
EXPECT_EQ(1, callCount); EXPECT_EQ(1, callCount);
} }
#endif
} }
......
...@@ -252,7 +252,6 @@ public: ...@@ -252,7 +252,6 @@ public:
// portion of each segment, whereas tryGetSegment() returns something that includes // portion of each segment, whereas tryGetSegment() returns something that includes
// not-yet-allocated space. // not-yet-allocated space.
#if !CAPNP_LITE
inline CapTableBuilder* getLocalCapTable() { inline CapTableBuilder* getLocalCapTable() {
// Return a CapTableBuilder that merely implements local loopback. That is, you can set // Return a CapTableBuilder that merely implements local loopback. That is, you can set
// capabilities, then read the same capabilities back, but there is no intent ever to transmit // capabilities, then read the same capabilities back, but there is no intent ever to transmit
...@@ -269,7 +268,6 @@ public: ...@@ -269,7 +268,6 @@ public:
return &localCapTable; return &localCapTable;
} }
#endif // !CAPNP_LITE
SegmentBuilder* getSegment(SegmentId id); SegmentBuilder* getSegment(SegmentId id);
// Get the segment with the given id. Crashes or throws an exception if no such segment exists. // Get the segment with the given id. Crashes or throws an exception if no such segment exists.
...@@ -304,8 +302,8 @@ private: ...@@ -304,8 +302,8 @@ private:
MessageBuilder* message; MessageBuilder* message;
ReadLimiter dummyLimiter; ReadLimiter dummyLimiter;
#if !CAPNP_LITE
class LocalCapTable: public CapTableBuilder { class LocalCapTable: public CapTableBuilder {
#if !CAPNP_LITE
public: public:
kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override; kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
uint injectCap(kj::Own<ClientHook>&& cap) override; uint injectCap(kj::Own<ClientHook>&& cap) override;
...@@ -313,10 +311,10 @@ private: ...@@ -313,10 +311,10 @@ private:
private: private:
kj::Vector<kj::Maybe<kj::Own<ClientHook>>> capTable; kj::Vector<kj::Maybe<kj::Own<ClientHook>>> capTable;
#endif // ! CAPNP_LITE
}; };
LocalCapTable localCapTable; LocalCapTable localCapTable;
#endif // !CAPNP_LITE
SegmentBuilder segment0; SegmentBuilder segment0;
kj::ArrayPtr<const word> segment0ForOutput; kj::ArrayPtr<const word> segment0ForOutput;
......
...@@ -77,9 +77,11 @@ using capnproto_test::capnp::test::TestInterface; ...@@ -77,9 +77,11 @@ using capnproto_test::capnp::test::TestInterface;
static_assert(equalTypes<FromAny<int>, int>(), ""); static_assert(equalTypes<FromAny<int>, int>(), "");
static_assert(equalTypes<FromAny<TestAllTypes::Reader>, TestAllTypes>(), ""); static_assert(equalTypes<FromAny<TestAllTypes::Reader>, TestAllTypes>(), "");
static_assert(equalTypes<FromAny<TestAllTypes::Builder>, TestAllTypes>(), ""); static_assert(equalTypes<FromAny<TestAllTypes::Builder>, TestAllTypes>(), "");
#if !CAPNP_LITE
static_assert(equalTypes<FromAny<TestAllTypes::Pipeline>, TestAllTypes>(), ""); static_assert(equalTypes<FromAny<TestAllTypes::Pipeline>, TestAllTypes>(), "");
static_assert(equalTypes<FromAny<TestInterface::Client>, TestInterface>(), ""); static_assert(equalTypes<FromAny<TestInterface::Client>, TestInterface>(), "");
static_assert(equalTypes<FromAny<kj::Own<TestInterface::Server>>, TestInterface>(), ""); static_assert(equalTypes<FromAny<kj::Own<TestInterface::Server>>, TestInterface>(), "");
#endif
} // namespace } // namespace
} // namespace capnp } // namespace capnp
...@@ -127,18 +127,7 @@ struct EnumInfo; ...@@ -127,18 +127,7 @@ struct EnumInfo;
namespace _ { // private namespace _ { // private
template <typename T, typename = typename T::_capnpPrivate::IsStruct> uint8_t kindSfinae(int); template <typename T, typename = void> struct Kind_;
template <typename T, typename = typename T::_capnpPrivate::IsInterface> uint16_t kindSfinae(int);
template <typename T, typename = typename schemas::EnumInfo<T>::IsEnum> uint32_t kindSfinae(int);
template <typename T> uint64_t kindSfinae(...);
template <typename T>
struct MsvcWorkaround {
// TODO(msvc): Remove this once MSVC supports expression SFINAE.
enum { value = sizeof(kindSfinae<T>(0)) };
};
template <typename T, size_t s = MsvcWorkaround<T>::value> struct Kind_;
template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
...@@ -155,19 +144,18 @@ template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; ...@@ -155,19 +144,18 @@ template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE;
template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; }; template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; }; template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };
template <typename T> struct Kind_<T, sizeof(uint8_t)> { static constexpr Kind kind = Kind::STRUCT; }; template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
template <typename T> struct Kind_<T, sizeof(uint16_t)> { static constexpr Kind kind = Kind::INTERFACE; }; static constexpr Kind kind = Kind::STRUCT;
template <typename T> struct Kind_<T, sizeof(uint32_t)> { static constexpr Kind kind = Kind::ENUM; }; };
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
static constexpr Kind kind = Kind::INTERFACE;
};
template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
static constexpr Kind kind = Kind::ENUM;
};
} // namespace _ (private) } // namespace _ (private)
#if CAPNP_LITE
#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
// Avoid constexpr methods in lite mode (MSVC is bad at constexpr).
#else // CAPNP_LITE
template <typename T, Kind k = _::Kind_<T>::kind> template <typename T, Kind k = _::Kind_<T>::kind>
inline constexpr Kind kind() { inline constexpr Kind kind() {
// This overload of kind() matches types which have a Kind_ specialization. // This overload of kind() matches types which have a Kind_ specialization.
...@@ -175,6 +163,13 @@ inline constexpr Kind kind() { ...@@ -175,6 +163,13 @@ inline constexpr Kind kind() {
return k; return k;
} }
#if CAPNP_LITE
#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
// Avoid constexpr methods in lite mode (MSVC is bad at constexpr).
#else // CAPNP_LITE
#define CAPNP_KIND(T) ::capnp::kind<T>() #define CAPNP_KIND(T) ::capnp::kind<T>()
// Use this macro rather than kind<T>() in any code which must work in lite mode. // Use this macro rather than kind<T>() in any code which must work in lite mode.
...@@ -206,7 +201,7 @@ template <typename T> struct ListElementType_<List<T>> { typedef T Type; }; ...@@ -206,7 +201,7 @@ template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
template <typename T> using ListElementType = typename ListElementType_<T>::Type; template <typename T> using ListElementType = typename ListElementType_<T>::Type;
namespace _ { // private namespace _ { // private
template <typename T, Kind k> struct Kind_<List<T, k>, sizeof(uint64_t)> { template <typename T, Kind k> struct Kind_<List<T, k>> {
static constexpr Kind kind = Kind::LIST; static constexpr Kind kind = Kind::LIST;
}; };
} // namespace _ (private) } // namespace _ (private)
...@@ -255,18 +250,42 @@ template <typename T> ...@@ -255,18 +250,42 @@ template <typename T>
using FromServer = typename kj::Decay<T>::Serves; using FromServer = typename kj::Decay<T>::Serves;
// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type). // FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
struct FromAny_ { template <typename T, typename = void>
template <typename T, typename X = FromReader<T>> static X apply(T*, int); struct FromAny_;
template <typename T, typename X = FromBuilder<T>> static X apply(T*, char);
template <typename T, typename X = FromPipeline<T>> static X apply(T*, long); template <typename T>
// note that ::Client is covered by FromReader struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
template <typename T, typename X = FromServer<T>> static X apply(kj::Own<T>*, short); using Type = FromReader<T>;
template <typename T, typename = kj::EnableIf<style<T>() == Style::PRIMITIVE>> };
static T apply(T*, unsigned int);
template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
using Type = FromBuilder<T>;
};
template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
using Type = FromPipeline<T>;
};
// Note that T::Client is covered by FromReader
template <typename T>
struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
using Type = FromServer<T>;
};
template <typename T>
struct FromAny_<T,
kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
// TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
// cannot yet use style<T>() in this constexpr context.
using Type = kj::Decay<T>;
}; };
template <typename T> template <typename T>
using FromAny = kj::Decay<decltype(FromAny_::apply(kj::instance<T*>(), 0))>; using FromAny = typename FromAny_<T>::Type;
// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is: // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
// //
// Foo::Reader -> Foo // Foo::Reader -> Foo
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <capnp/schema.capnp.h> #include <capnp/schema.capnp.h>
#include <kj/vector.h> #include <kj/vector.h>
#include <kj/io.h> #include <kj/io.h>
#include <unistd.h> #include <kj/miniposix.h>
#include <kj/debug.h> #include <kj/debug.h>
#include "../message.h" #include "../message.h"
#include <iostream> #include <iostream>
...@@ -43,9 +43,6 @@ ...@@ -43,9 +43,6 @@
#if _WIN32 #if _WIN32
#include <process.h> #include <process.h>
#include <io.h>
#include <fcntl.h>
#define pipe(fds) _pipe(fds, 8192, _O_BINARY)
#else #else
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
...@@ -447,7 +444,7 @@ public: ...@@ -447,7 +444,7 @@ public:
} }
int pipeFds[2]; int pipeFds[2];
KJ_SYSCALL(pipe(pipeFds)); KJ_SYSCALL(kj::miniposix::pipe(pipeFds));
kj::String exeName; kj::String exeName;
bool shouldSearchPath = true; bool shouldSearchPath = true;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <kj/vector.h> #include <kj/vector.h>
#include "../schema-loader.h" #include "../schema-loader.h"
#include "../dynamic.h" #include "../dynamic.h"
#include <unistd.h> #include <kj/miniposix.h>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <map> #include <map>
...@@ -50,10 +50,6 @@ ...@@ -50,10 +50,6 @@
#define VERSION "(unknown)" #define VERSION "(unknown)"
#endif #endif
#if _WIN32
#define mkdir(path, mode) mkdir(path)
#endif
namespace capnp { namespace capnp {
namespace { namespace {
...@@ -2917,7 +2913,7 @@ private: ...@@ -2917,7 +2913,7 @@ private:
makeDirectory(kj::str(path.slice(0, *slashpos))); makeDirectory(kj::str(path.slice(0, *slashpos)));
} }
if (mkdir(path.cStr(), 0777) < 0) { if (kj::miniposix::mkdir(path.cStr(), 0777) < 0) {
int error = errno; int error = errno;
if (error != EEXIST) { if (error != EEXIST) {
KJ_FAIL_SYSCALL("mkdir(path)", error, path); KJ_FAIL_SYSCALL("mkdir(path)", error, path);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <kj/vector.h> #include <kj/vector.h>
#include "../schema-loader.h" #include "../schema-loader.h"
#include "../dynamic.h" #include "../dynamic.h"
#include <unistd.h> #include <kj/miniposix.h>
#include <unordered_map> #include <unordered_map>
#include <kj/main.h> #include <kj/main.h>
#include <algorithm> #include <algorithm>
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <time.h> #include <time.h>
#include <kj/main.h> #include <kj/main.h>
#include <kj/io.h> #include <kj/io.h>
#include <unistd.h> #include <kj/miniposix.h>
namespace capnp { namespace capnp {
namespace compiler { namespace compiler {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <kj/io.h> #include <kj/io.h>
#include <capnp/message.h> #include <capnp/message.h>
#include <map> #include <map>
#include <unistd.h> #include <kj/miniposix.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -99,7 +99,7 @@ kj::Array<const byte> mmapForRead(kj::StringPtr filename) { ...@@ -99,7 +99,7 @@ kj::Array<const byte> mmapForRead(kj::StringPtr filename) {
byte buffer[4096]; byte buffer[4096];
for (;;) { for (;;) {
ssize_t n; kj::miniposix::ssize_t n;
KJ_SYSCALL(n = read(fd, buffer, sizeof(buffer))); KJ_SYSCALL(n = read(fd, buffer, sizeof(buffer)));
if (n == 0) break; if (n == 0) break;
data.addAll(buffer, buffer + n); data.addAll(buffer, buffer + n);
......
...@@ -1667,6 +1667,8 @@ TEST(Encoding, Embeds) { ...@@ -1667,6 +1667,8 @@ TEST(Encoding, Embeds) {
checkTestMessage(reader.getRoot<TestAllTypes>()); checkTestMessage(reader.getRoot<TestAllTypes>());
} }
#if !CAPNP_LITE
{ {
MallocMessageBuilder builder; MallocMessageBuilder builder;
auto root = builder.getRoot<TestAllTypes>(); auto root = builder.getRoot<TestAllTypes>();
...@@ -1675,6 +1677,8 @@ TEST(Encoding, Embeds) { ...@@ -1675,6 +1677,8 @@ TEST(Encoding, Embeds) {
EXPECT_EQ(kj::str(root, '\n').size(), text.size()); EXPECT_EQ(kj::str(root, '\n').size(), text.size());
} }
#endif // CAPNP_LITE
{ {
checkTestMessage(test::EMBEDDED_STRUCT); checkTestMessage(test::EMBEDDED_STRUCT);
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "serialize.h" #include "serialize.h"
#include <kj/test.h> #include <kj/test.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <kj/miniposix.h>
#include "test-util.h" #include "test-util.h"
namespace capnp { namespace capnp {
......
...@@ -36,9 +36,11 @@ namespace { ...@@ -36,9 +36,11 @@ namespace {
class DummyCapTableReader: public _::CapTableReader { class DummyCapTableReader: public _::CapTableReader {
public: public:
#if !CAPNP_LITE
kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override { kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override {
return nullptr; return nullptr;
} }
#endif
}; };
static constexpr DummyCapTableReader dummyCapTableReader = DummyCapTableReader(); static constexpr DummyCapTableReader dummyCapTableReader = DummyCapTableReader();
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <kj/vector.h> #include <kj/vector.h>
#include <kj/debug.h> #include <kj/debug.h>
#include <kj/io.h> #include <kj/io.h>
#include <unistd.h> #include <kj/miniposix.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -400,7 +400,7 @@ kj::Array<const char> SchemaFile::DiskFileReader::read(kj::StringPtr path) const ...@@ -400,7 +400,7 @@ kj::Array<const char> SchemaFile::DiskFileReader::read(kj::StringPtr path) const
char buffer[4096]; char buffer[4096];
for (;;) { for (;;) {
ssize_t n; kj::miniposix::ssize_t n;
KJ_SYSCALL(n = ::read(fd, buffer, sizeof(buffer))); KJ_SYSCALL(n = ::read(fd, buffer, sizeof(buffer)));
if (n == 0) break; if (n == 0) break;
data.addAll(buffer, buffer + n); data.addAll(buffer, buffer + n);
......
...@@ -11,13 +11,13 @@ set(kj_sources_lite ...@@ -11,13 +11,13 @@ set(kj_sources_lite
mutex.c++ mutex.c++
string.c++ string.c++
thread.c++ thread.c++
main.c++
arena.c++
) )
set(kj_sources_heavy set(kj_sources_heavy
units.c++ units.c++
refcount.c++ refcount.c++
string-tree.c++ string-tree.c++
arena.c++
main.c++
parse/char.c++ parse/char.c++
) )
if(NOT CAPNP_LITE) if(NOT CAPNP_LITE)
......
...@@ -340,6 +340,10 @@ template <bool b> using EnableIf = typename EnableIf_<b>::Type; ...@@ -340,6 +340,10 @@ template <bool b> using EnableIf = typename EnableIf_<b>::Type;
// template <typename T, typename = EnableIf<isValid<T>()> // template <typename T, typename = EnableIf<isValid<T>()>
// void func(T&& t); // void func(T&& t);
template <typename...> struct VoidSfinae_ { using Type = void; };
template <typename... Ts> using VoidSfinae = typename VoidSfinae_<Ts...>::Type;
// Note: VoidSfinae is std::void_t from C++17.
template <typename T> template <typename T>
T instance() noexcept; T instance() noexcept;
// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify // Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
...@@ -790,6 +794,15 @@ class Maybe; ...@@ -790,6 +794,15 @@ class Maybe;
namespace _ { // private namespace _ { // private
#if _MSC_VER
// TODO(msvc): MSVC barfs on noexcept(instance<T&>().~T()) where T = kj::Exception and
// kj::_::Void. It and every other factorization I've tried produces:
// error C2325: 'kj::Blah' unexpected type to the right of '.~': expected 'void'
#define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) __is_nothrow_destructible(T)
#else
#define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) noexcept(instance<T&>().~T())
#endif
template <typename T> template <typename T>
class NullableValue { class NullableValue {
// Class whose interface behaves much like T*, but actually contains an instance of T and a // Class whose interface behaves much like T*, but actually contains an instance of T and a
...@@ -814,7 +827,7 @@ public: ...@@ -814,7 +827,7 @@ public:
ctor(value, other.value); ctor(value, other.value);
} }
} }
inline ~NullableValue() noexcept(noexcept(instance<T&>().~T())) { inline ~NullableValue() noexcept(MSVC_NOEXCEPT_DTOR_WORKAROUND(T)) {
if (isSet) { if (isSet) {
dtor(value); dtor(value);
} }
......
...@@ -22,17 +22,17 @@ ...@@ -22,17 +22,17 @@
#include "main.h" #include "main.h"
#include "debug.h" #include "debug.h"
#include "arena.h" #include "arena.h"
#include "miniposix.h"
#include <map> #include <map>
#include <set> #include <set>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#if _WIN32 #if _WIN32
#define NOMINMAX
#include <windows.h> #include <windows.h>
#include <io.h> #undef NOMINMAX
#include <fcntl.h>
#else #else
#include <sys/uio.h> #include <sys/uio.h>
#endif #endif
......
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#ifndef KJ_PORTABLE_FD_H_ #ifndef KJ_MINIPOSIX_H_
#define KJ_PORTABLE_FD_H_ #define KJ_MINIPOSIX_H_
// This header provides a small subset of the POSIX API which also happens to be available on // This header provides a small subset of the POSIX API which also happens to be available on
// Windows under slightly-different names. // Windows under slightly-different names.
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#if _WIN32 #if _WIN32
#include <io.h> #include <io.h>
#include <direct.h> #include <direct.h>
#include <fcntl.h> // _O_BINARY
#else #else
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
...@@ -61,6 +62,17 @@ inline int close(int fd) { ...@@ -61,6 +62,17 @@ inline int close(int fd) {
return ::_close(fd); return ::_close(fd);
} }
#ifndef F_OK
#define F_OK 0 // access() existence test
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // stat() regular file test
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // stat() directory test
#endif
#ifndef STDIN_FILENO #ifndef STDIN_FILENO
#define STDIN_FILENO 0 #define STDIN_FILENO 0
#endif #endif
...@@ -85,7 +97,7 @@ using ::close; ...@@ -85,7 +97,7 @@ using ::close;
// We're on Windows, including MinGW. pipe() and mkdir() are non-standard even on MinGW. // We're on Windows, including MinGW. pipe() and mkdir() are non-standard even on MinGW.
inline int pipe(int fds[2]) { inline int pipe(int fds[2]) {
return ::_pipe(fds, 4096, false); return ::_pipe(fds, 8192, _O_BINARY);
} }
inline int mkdir(const char* path, int mode) { inline int mkdir(const char* path, int mode) {
return ::_mkdir(path); return ::_mkdir(path);
...@@ -133,4 +145,4 @@ inline size_t iovMax(size_t count) { ...@@ -133,4 +145,4 @@ inline size_t iovMax(size_t count) {
} // namespace miniposix } // namespace miniposix
} // namespace kj } // namespace kj
#endif // KJ_WIN32_FD_H_ #endif // KJ_MINIPOSIX_H_
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
#include <kj/compat/gtest.h> #include <kj/compat/gtest.h>
#if _WIN32 #if _WIN32
#define NOGDI // NOGDI is needed to make EXPECT_EQ(123u, *lock) compile for some reason
#include <windows.h> #include <windows.h>
#undef NOGDI
#else #else
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
......
...@@ -67,10 +67,6 @@ struct Id { ...@@ -67,10 +67,6 @@ struct Id {
// ======================================================================================= // =======================================================================================
// Quantity and UnitRatio -- implement unit analysis via the type system // Quantity and UnitRatio -- implement unit analysis via the type system
#if !_MSC_VER
// TODO(msvc): MSVC has trouble with this intense templating. Luckily Cap'n Proto can deal with
// using regular integers in place of Quantity, so we can just skip all this.
template <typename T> constexpr bool isIntegral() { return false; } template <typename T> constexpr bool isIntegral() { return false; }
template <> constexpr bool isIntegral<char>() { return true; } template <> constexpr bool isIntegral<char>() { return true; }
template <> constexpr bool isIntegral<signed char>() { return true; } template <> constexpr bool isIntegral<signed char>() { return true; }
...@@ -225,9 +221,12 @@ class Quantity { ...@@ -225,9 +221,12 @@ class Quantity {
public: public:
inline constexpr Quantity() {} inline constexpr Quantity() {}
inline constexpr Quantity(decltype(maxValue)): value(maxValue) {} inline constexpr Quantity(MaxValue_): value(maxValue) {}
inline constexpr Quantity(decltype(minValue)): value(minValue) {} inline constexpr Quantity(MinValue_): value(minValue) {}
// Allow initialization from maxValue and minValue. // Allow initialization from maxValue and minValue.
// TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function
// parameters, causing the compiler to complain of a duplicate constructor definition, so we
// specify MaxValue_ and MinValue_ types explicitly.
inline explicit constexpr Quantity(Number value): value(value) {} inline explicit constexpr Quantity(Number value): value(value) {}
// This constructor was intended to be private, but GCC complains about it being private in a // This constructor was intended to be private, but GCC complains about it being private in a
...@@ -354,15 +353,11 @@ private: ...@@ -354,15 +353,11 @@ private:
friend inline constexpr T unit(); friend inline constexpr T unit();
}; };
#endif // !_MSC_VER
template <typename T> template <typename T>
inline constexpr T unit() { return T(1); } inline constexpr T unit() { return T(1); }
// unit<Quantity<T, U>>() returns a Quantity of value 1. It also, intentionally, works on basic // unit<Quantity<T, U>>() returns a Quantity of value 1. It also, intentionally, works on basic
// numeric types. // numeric types.
#if !_MSC_VER
template <typename Number1, typename Number2, typename Unit> template <typename Number1, typename Number2, typename Unit>
inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit> b) inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit> b)
-> Quantity<decltype(Number1(1) * Number2(1)), Unit> { -> Quantity<decltype(Number1(1) * Number2(1)), Unit> {
...@@ -433,8 +428,6 @@ inline constexpr T origin() { return T(0 * unit<UnitOf<T>>()); } ...@@ -433,8 +428,6 @@ inline constexpr T origin() { return T(0 * unit<UnitOf<T>>()); }
// origin<Absolute<T, U>>() returns an Absolute of value 0. It also, intentionally, works on basic // origin<Absolute<T, U>>() returns an Absolute of value 0. It also, intentionally, works on basic
// numeric types. // numeric types.
#endif // !_MSC_VER
} // namespace kj } // namespace kj
#endif // KJ_UNITS_H_ #endif // KJ_UNITS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment