Commit b0868e34 authored by Kenton Varda's avatar Kenton Varda

Replace some STL maps with KJ maps in Cap'n Proto implementation.

So far this is only a small subset of all the STL uses.
parent e443282b
......@@ -98,11 +98,10 @@ SegmentReader* ReaderArena::tryGetSegment(SegmentId id) {
SegmentMap* segments = nullptr;
KJ_IF_MAYBE(s, *lock) {
auto iter = s->get()->find(id.value);
if (iter != s->get()->end()) {
return iter->second;
KJ_IF_MAYBE(segment, s->find(id.value)) {
return *segment;
}
segments = *s;
segments = s;
}
kj::ArrayPtr<const word> newSegment = message->getSegment(id.value);
......@@ -114,15 +113,13 @@ SegmentReader* ReaderArena::tryGetSegment(SegmentId id) {
if (*lock == nullptr) {
// OK, the segment exists, so allocate the map.
auto s = kj::heap<SegmentMap>();
segments = s;
*lock = kj::mv(s);
segments = &lock->emplace();
}
auto segment = kj::heap<SegmentReader>(
this, id, newSegment.begin(), newSegmentSize, &readLimiter);
SegmentReader* result = segment;
segments->insert(std::make_pair(id.value, mv(segment)));
segments->insert(id.value, kj::mv(segment));
return result;
}
......
......@@ -37,7 +37,7 @@
#include "common.h"
#include "message.h"
#include "layout.h"
#include <unordered_map>
#include <kj/map.h>
#if !CAPNP_LITE
#include "capability.h"
......@@ -241,8 +241,8 @@ private:
// Optimize for single-segment messages so that small messages are handled quickly.
SegmentReader segment0;
typedef std::unordered_map<uint, kj::Own<SegmentReader>> SegmentMap;
kj::MutexGuarded<kj::Maybe<kj::Own<SegmentMap>>> moreSegments;
typedef kj::HashMap<uint, kj::Own<SegmentReader>> SegmentMap;
kj::MutexGuarded<kj::Maybe<SegmentMap>> moreSegments;
// We need to mutex-guard the segment map because we lazily initialize segments when they are
// first requested, but a Reader is allowed to be used concurrently in multiple threads. Luckily
// this only applies to large messages.
......
......@@ -46,6 +46,7 @@
#include <capnp/compat/json.h>
#include <errno.h>
#include <stdlib.h>
#include <kj/map.h>
#if _WIN32
#include <process.h>
......@@ -1767,17 +1768,16 @@ private:
// require to function.
struct SourceDirectory {
kj::Path path;
kj::Own<const kj::ReadableDirectory> dir;
bool isSourcePrefix;
};
std::map<kj::PathPtr, SourceDirectory> sourceDirectories;
kj::HashMap<kj::Path, SourceDirectory> sourceDirectories;
// For each import path and source prefix, tracks the directory object we opened for it.
//
// Use via getSourceDirectory().
std::map<const kj::ReadableDirectory*, kj::String> dirPrefixes;
kj::HashMap<const kj::ReadableDirectory*, kj::String> dirPrefixes;
// For each open directory object, maps to a path prefix to add when displaying this path in
// error messages. This keeps track of the original directory name as given by the user, before
// canonicalization.
......@@ -1827,10 +1827,9 @@ private:
if (path.size() == 0) return disk->getRoot();
auto iter = sourceDirectories.find(path);
if (iter != sourceDirectories.end()) {
iter->second.isSourcePrefix = iter->second.isSourcePrefix || isSourcePrefix;
return *iter->second.dir;
KJ_IF_MAYBE(sdir, sourceDirectories.find(path)) {
sdir->isSourcePrefix = sdir->isSourcePrefix || isSourcePrefix;
return *sdir->dir;
}
if (path == cwd) {
......@@ -1843,26 +1842,22 @@ private:
// getDisplayName().
auto& result = disk->getCurrent();
if (isSourcePrefix) {
kj::PathPtr key = path;
kj::Own<const kj::ReadableDirectory> fakeOwn(&result, kj::NullDisposer::instance);
KJ_ASSERT(sourceDirectories.insert(std::make_pair(key,
SourceDirectory { kj::mv(path), kj::mv(fakeOwn), isSourcePrefix })).second);
sourceDirectories.insert(kj::mv(path), { kj::mv(fakeOwn), isSourcePrefix });
}
return result;
}
KJ_IF_MAYBE(dir, disk->getRoot().tryOpenSubdir(path)) {
auto& result = *dir->get();
kj::PathPtr key = path;
KJ_ASSERT(sourceDirectories.insert(std::make_pair(key,
SourceDirectory { kj::mv(path), kj::mv(*dir), isSourcePrefix })).second);
sourceDirectories.insert(kj::mv(path), { kj::mv(*dir), isSourcePrefix });
#if _WIN32
kj::String prefix = pathStr.endsWith("/") || pathStr.endsWith("\\")
? kj::str(pathStr) : kj::str(pathStr, '\\');
#else
kj::String prefix = pathStr.endsWith("/") ? kj::str(pathStr) : kj::str(pathStr, '/');
#endif
KJ_ASSERT(dirPrefixes.insert(std::make_pair(&result, kj::mv(prefix))).second);
dirPrefixes.insert(&result, kj::mv(prefix));
return result;
} else {
return nullptr;
......@@ -1883,9 +1878,8 @@ private:
auto prefix = path.slice(0, i);
auto remainder = path.slice(i, path.size());
auto iter = sourceDirectories.find(prefix);
if (iter != sourceDirectories.end() && iter->second.isSourcePrefix) {
return { *iter->second.dir, remainder.clone() };
KJ_IF_MAYBE(sdir, sourceDirectories.find(prefix)) {
return { *sdir->dir, remainder.clone() };
}
}
......@@ -1914,9 +1908,8 @@ private:
}
kj::String getDisplayName(const kj::ReadableDirectory& dir, kj::PathPtr path) {
auto iter = dirPrefixes.find(&dir);
if (iter != dirPrefixes.end()) {
return kj::str(iter->second, path.toNativeString());
KJ_IF_MAYBE(prefix, dirPrefixes.find(&dir)) {
return kj::str(*prefix, path.toNativeString());
} else if (&dir == &disk->getRoot()) {
return path.toNativeString(true);
} else if (&dir == &disk->getCurrent()) {
......
......@@ -126,9 +126,9 @@ private:
// Space in which we can construct a ReaderArena. We don't use ReaderArena directly here
// because we don't want clients to have to #include arena.h, which itself includes a bunch of
// big STL headers. We don't use a pointer to a ReaderArena because that would require an
// other headers. We don't use a pointer to a ReaderArena because that would require an
// extra malloc on every message which could be expensive when processing small messages.
void* arenaSpace[15 + sizeof(kj::MutexGuarded<void*>) / sizeof(void*)];
void* arenaSpace[17 + sizeof(kj::MutexGuarded<void*>) / sizeof(void*)];
bool allocatedArena;
_::ReaderArena* arena() { return reinterpret_cast<_::ReaderArena*>(arenaSpace); }
......
This diff is collapsed.
......@@ -26,6 +26,7 @@
#include <inttypes.h>
#include "time.h"
#include "function.h"
#include "hash.h"
namespace kj {
......@@ -156,6 +157,9 @@ public:
bool operator>=(PathPtr other) const;
// Compare path components lexically.
uint hashCode() const;
// Can use in HashMap.
bool startsWith(PathPtr prefix) const;
bool endsWith(PathPtr suffix) const;
// Compare prefix / suffix.
......@@ -264,6 +268,7 @@ public:
bool operator> (PathPtr other) const;
bool operator<=(PathPtr other) const;
bool operator>=(PathPtr other) const;
uint hashCode() const;
bool startsWith(PathPtr prefix) const;
bool endsWith(PathPtr suffix) const;
Path evalWin32(StringPtr pathText) const;
......@@ -991,6 +996,7 @@ inline bool Path::operator< (PathPtr other) const { return PathPtr(*this) < oth
inline bool Path::operator> (PathPtr other) const { return PathPtr(*this) > other; }
inline bool Path::operator<=(PathPtr other) const { return PathPtr(*this) <= other; }
inline bool Path::operator>=(PathPtr other) const { return PathPtr(*this) >= other; }
inline uint Path::hashCode() const { return kj::hashCode(parts); }
inline bool Path::startsWith(PathPtr prefix) const { return PathPtr(*this).startsWith(prefix); }
inline bool Path::endsWith (PathPtr suffix) const { return PathPtr(*this).endsWith (suffix); }
inline String Path::toString(bool absolute) const { return PathPtr(*this).toString(absolute); }
......@@ -1020,6 +1026,7 @@ inline bool PathPtr::operator!=(PathPtr other) const { return !(*this == other);
inline bool PathPtr::operator> (PathPtr other) const { return other < *this; }
inline bool PathPtr::operator<=(PathPtr other) const { return !(other < *this); }
inline bool PathPtr::operator>=(PathPtr other) const { return !(*this < other); }
inline uint PathPtr::hashCode() const { return kj::hashCode(parts); }
inline String PathPtr::toWin32String(bool absolute) const {
return toWin32StringImpl(absolute, false);
}
......
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