Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
48547eb6
Unverified
Commit
48547eb6
authored
Apr 01, 2019
by
Kenton Varda
Committed by
GitHub
Apr 01, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #811 from capnproto/feature-grab-bag
Feature grab bag
parents
ad87e243
ddd90bee
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
242 additions
and
3 deletions
+242
-3
array.h
c++/src/kj/array.h
+10
-2
map.h
c++/src/kj/map.h
+54
-0
mutex-test.c++
c++/src/kj/mutex-test.c++
+91
-0
mutex.h
c++/src/kj/mutex.h
+77
-0
one-of.h
c++/src/kj/one-of.h
+8
-0
vector.h
c++/src/kj/vector.h
+2
-1
No files found.
c++/src/kj/array.h
View file @
48547eb6
...
...
@@ -162,7 +162,11 @@ public:
}
inline
size_t
size
()
const
{
return
size_
;
}
inline
T
&
operator
[](
size_t
index
)
const
{
inline
T
&
operator
[](
size_t
index
)
{
KJ_IREQUIRE
(
index
<
size_
,
"Out-of-bounds Array access."
);
return
ptr
[
index
];
}
inline
const
T
&
operator
[](
size_t
index
)
const
{
KJ_IREQUIRE
(
index
<
size_
,
"Out-of-bounds Array access."
);
return
ptr
[
index
];
}
...
...
@@ -356,7 +360,11 @@ public:
inline
size_t
size
()
const
{
return
pos
-
ptr
;
}
inline
size_t
capacity
()
const
{
return
endPtr
-
ptr
;
}
inline
T
&
operator
[](
size_t
index
)
const
{
inline
T
&
operator
[](
size_t
index
)
{
KJ_IREQUIRE
(
index
<
implicitCast
<
size_t
>
(
pos
-
ptr
),
"Out-of-bounds Array access."
);
return
ptr
[
index
];
}
inline
const
T
&
operator
[](
size_t
index
)
const
{
KJ_IREQUIRE
(
index
<
implicitCast
<
size_t
>
(
pos
-
ptr
),
"Out-of-bounds Array access."
);
return
ptr
[
index
];
}
...
...
c++/src/kj/map.h
View file @
48547eb6
...
...
@@ -87,6 +87,14 @@ public:
// Like find() but if the key isn't present then call createEntry() to create the corresponding
// entry and insert it. createEntry() must return type `Entry`.
template
<
typename
KeyLike
>
kj
::
Maybe
<
Entry
&>
findEntry
(
KeyLike
&&
key
);
template
<
typename
KeyLike
>
kj
::
Maybe
<
const
Entry
&>
findEntry
(
KeyLike
&&
key
)
const
;
template
<
typename
KeyLike
,
typename
Func
>
Entry
&
findOrCreateEntry
(
KeyLike
&&
key
,
Func
&&
createEntry
);
// Sometimes you need to see the whole matching Entry, not just the Value.
template
<
typename
KeyLike
>
bool
erase
(
KeyLike
&&
key
);
// Erase the entry with the matching key.
...
...
@@ -176,6 +184,14 @@ public:
// Like find() but if the key isn't present then call createEntry() to create the corresponding
// entry and insert it. createEntry() must return type `Entry`.
template
<
typename
KeyLike
>
kj
::
Maybe
<
Entry
&>
findEntry
(
KeyLike
&&
key
);
template
<
typename
KeyLike
>
kj
::
Maybe
<
const
Entry
&>
findEntry
(
KeyLike
&&
key
)
const
;
template
<
typename
KeyLike
,
typename
Func
>
Entry
&
findOrCreateEntry
(
KeyLike
&&
key
,
Func
&&
createEntry
);
// Sometimes you need to see the whole matching Entry, not just the Value.
template
<
typename
K1
,
typename
K2
>
auto
range
(
K1
&&
k1
,
K2
&&
k2
);
template
<
typename
K1
,
typename
K2
>
...
...
@@ -353,6 +369,25 @@ Value& HashMap<Key, Value>::findOrCreate(KeyLike&& key, Func&& createEntry) {
return
table
.
findOrCreate
(
key
,
kj
::
fwd
<
Func
>
(
createEntry
)).
value
;
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
>
kj
::
Maybe
<
typename
HashMap
<
Key
,
Value
>::
Entry
&>
HashMap
<
Key
,
Value
>::
findEntry
(
KeyLike
&&
key
)
{
return
table
.
find
(
kj
::
fwd
<
KeyLike
>
(
key
));
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
>
kj
::
Maybe
<
const
typename
HashMap
<
Key
,
Value
>::
Entry
&>
HashMap
<
Key
,
Value
>::
findEntry
(
KeyLike
&&
key
)
const
{
return
table
.
find
(
kj
::
fwd
<
KeyLike
>
(
key
));
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
,
typename
Func
>
typename
HashMap
<
Key
,
Value
>::
Entry
&
HashMap
<
Key
,
Value
>::
findOrCreateEntry
(
KeyLike
&&
key
,
Func
&&
createEntry
)
{
return
table
.
findOrCreate
(
kj
::
fwd
<
KeyLike
>
(
key
),
kj
::
fwd
<
Func
>
(
createEntry
));
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
>
bool
HashMap
<
Key
,
Value
>::
erase
(
KeyLike
&&
key
)
{
...
...
@@ -445,6 +480,25 @@ Value& TreeMap<Key, Value>::findOrCreate(KeyLike&& key, Func&& createEntry) {
return
table
.
findOrCreate
(
key
,
kj
::
fwd
<
Func
>
(
createEntry
)).
value
;
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
>
kj
::
Maybe
<
typename
TreeMap
<
Key
,
Value
>::
Entry
&>
TreeMap
<
Key
,
Value
>::
findEntry
(
KeyLike
&&
key
)
{
return
table
.
find
(
kj
::
fwd
<
KeyLike
>
(
key
));
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
>
kj
::
Maybe
<
const
typename
TreeMap
<
Key
,
Value
>::
Entry
&>
TreeMap
<
Key
,
Value
>::
findEntry
(
KeyLike
&&
key
)
const
{
return
table
.
find
(
kj
::
fwd
<
KeyLike
>
(
key
));
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
KeyLike
,
typename
Func
>
typename
TreeMap
<
Key
,
Value
>::
Entry
&
TreeMap
<
Key
,
Value
>::
findOrCreateEntry
(
KeyLike
&&
key
,
Func
&&
createEntry
)
{
return
table
.
findOrCreate
(
kj
::
fwd
<
KeyLike
>
(
key
),
kj
::
fwd
<
Func
>
(
createEntry
));
}
template
<
typename
Key
,
typename
Value
>
template
<
typename
K1
,
typename
K2
>
auto
TreeMap
<
Key
,
Value
>::
range
(
K1
&&
k1
,
K2
&&
k2
)
{
...
...
c++/src/kj/mutex-test.c++
View file @
48547eb6
...
...
@@ -221,5 +221,96 @@ TEST(Mutex, LazyException) {
#endif
}
class
OnlyTouchUnderLock
{
public
:
OnlyTouchUnderLock
()
:
ptr
(
nullptr
)
{}
OnlyTouchUnderLock
(
MutexGuarded
<
uint
>&
ref
)
:
ptr
(
&
ref
)
{
ptr
->
getAlreadyLockedExclusive
()
++
;
}
OnlyTouchUnderLock
(
OnlyTouchUnderLock
&&
other
)
:
ptr
(
other
.
ptr
)
{
other
.
ptr
=
nullptr
;
if
(
ptr
)
{
// Just verify it's locked. Don't increment because different compilers may or may not
// elide moves.
ptr
->
getAlreadyLockedExclusive
();
}
}
OnlyTouchUnderLock
&
operator
=
(
OnlyTouchUnderLock
&&
other
)
{
if
(
ptr
)
{
ptr
->
getAlreadyLockedExclusive
()
++
;
}
ptr
=
other
.
ptr
;
other
.
ptr
=
nullptr
;
if
(
ptr
)
{
// Just verify it's locked. Don't increment because different compilers may or may not
// elide moves.
ptr
->
getAlreadyLockedExclusive
();
}
return
*
this
;
}
~
OnlyTouchUnderLock
()
noexcept
(
false
)
{
if
(
ptr
!=
nullptr
)
{
ptr
->
getAlreadyLockedExclusive
()
++
;
}
}
void
frob
()
{
ptr
->
getAlreadyLockedExclusive
()
++
;
}
private
:
MutexGuarded
<
uint
>*
ptr
;
};
KJ_TEST
(
"ExternalMutexGuarded<T> destroy after release"
)
{
MutexGuarded
<
uint
>
guarded
(
0
);
{
ExternalMutexGuarded
<
OnlyTouchUnderLock
>
ext
;
{
auto
lock
=
guarded
.
lockExclusive
();
ext
.
set
(
lock
,
guarded
);
KJ_EXPECT
(
*
lock
==
1
,
*
lock
);
ext
.
get
(
lock
).
frob
();
KJ_EXPECT
(
*
lock
==
2
,
*
lock
);
}
{
auto
lock
=
guarded
.
lockExclusive
();
auto
released
=
ext
.
release
(
lock
);
KJ_EXPECT
(
*
lock
==
2
,
*
lock
);
released
.
frob
();
KJ_EXPECT
(
*
lock
==
3
,
*
lock
);
}
}
{
auto
lock
=
guarded
.
lockExclusive
();
KJ_EXPECT
(
*
lock
==
4
,
*
lock
);
}
}
KJ_TEST
(
"ExternalMutexGuarded<T> destroy without release"
)
{
MutexGuarded
<
uint
>
guarded
(
0
);
{
ExternalMutexGuarded
<
OnlyTouchUnderLock
>
ext
;
{
auto
lock
=
guarded
.
lockExclusive
();
ext
.
set
(
lock
,
guarded
);
KJ_EXPECT
(
*
lock
==
1
);
ext
.
get
(
lock
).
frob
();
KJ_EXPECT
(
*
lock
==
2
);
}
}
{
auto
lock
=
guarded
.
lockExclusive
();
KJ_EXPECT
(
*
lock
==
3
);
}
}
}
// namespace
}
// namespace kj
c++/src/kj/mutex.h
View file @
48547eb6
...
...
@@ -218,6 +218,8 @@ private:
template
<
typename
U
>
friend
class
MutexGuarded
;
template
<
typename
U
>
friend
class
ExternalMutexGuarded
;
};
template
<
typename
T
>
...
...
@@ -308,6 +310,81 @@ class MutexGuarded<const T> {
static_assert
(
sizeof
(
T
)
<
0
,
"MutexGuarded's type cannot be const."
);
};
template
<
typename
T
>
class
ExternalMutexGuarded
{
// Holds a value that can only be manipulated while some other mutex is locked.
//
// The ExternalMutexGuarded<T> lives *outside* the scope of any lock on the mutex, but ensures
// that the value it holds can only be accessed under lock by forcing the caller to present a
// lock before accessing the value.
//
// Additionally, ExternalMutexGuarded<T>'s destructor will take an exclusive lock on the mutex
// while destroying the held value, unless the value has been release()ed before hand.
//
// The type T must have the following properties (which probably all movable types satisfy):
// - T is movable.
// - Immediately after any of the following has happened, T's destructor is effectively a no-op
// (hence certainly not requiring locks):
// - The value has been default-constructed.
// - The value has been initialized by-move from a default-constructed T.
// - The value has been moved away.
// - If ExternalMutexGuarded<T> is ever moved, then T must have a move constructor and move
// assignment operator that do not follow any pointers, therefore do not need to take a lock.
public
:
ExternalMutexGuarded
()
=
default
;
~
ExternalMutexGuarded
()
noexcept
(
false
)
{
if
(
mutex
!=
nullptr
)
{
mutex
->
lock
(
_
::
Mutex
::
EXCLUSIVE
);
KJ_DEFER
(
mutex
->
unlock
(
_
::
Mutex
::
EXCLUSIVE
));
value
=
T
();
}
}
ExternalMutexGuarded
(
ExternalMutexGuarded
&&
other
)
:
mutex
(
other
.
mutex
),
value
(
kj
::
mv
(
other
.
value
))
{
other
.
mutex
=
nullptr
;
}
ExternalMutexGuarded
&
operator
=
(
ExternalMutexGuarded
&&
other
)
{
mutex
=
other
.
mutex
;
value
=
kj
::
mv
(
other
.
value
);
other
.
mutex
=
nullptr
;
return
*
this
;
}
template
<
typename
U
>
void
set
(
Locked
<
U
>&
lock
,
T
&&
newValue
)
{
KJ_IREQUIRE
(
mutex
==
nullptr
);
mutex
=
lock
.
mutex
;
value
=
kj
::
mv
(
newValue
);
}
template
<
typename
U
>
T
&
get
(
Locked
<
U
>&
lock
)
{
KJ_IREQUIRE
(
lock
.
mutex
==
mutex
);
return
value
;
}
template
<
typename
U
>
const
T
&
get
(
Locked
<
const
U
>&
lock
)
const
{
KJ_IREQUIRE
(
lock
.
mutex
==
mutex
);
return
value
;
}
template
<
typename
U
>
T
release
(
Locked
<
U
>&
lock
)
{
// Release (move away) the value. This allows the destructor to skip locking the mutex.
KJ_IREQUIRE
(
lock
.
mutex
==
mutex
);
T
result
=
kj
::
mv
(
value
);
mutex
=
nullptr
;
return
result
;
}
private
:
_
::
Mutex
*
mutex
=
nullptr
;
T
value
;
};
template
<
typename
T
>
class
Lazy
{
// A lazily-initialized value.
...
...
c++/src/kj/one-of.h
View file @
48547eb6
...
...
@@ -118,6 +118,14 @@ public:
return
nullptr
;
}
}
template
<
typename
T
>
Maybe
<
const
T
&>
tryGet
()
const
{
if
(
is
<
T
>
())
{
return
*
reinterpret_cast
<
const
T
*>
(
space
);
}
else
{
return
nullptr
;
}
}
template
<
uint
i
>
KJ_NORETURN
(
void
allHandled
());
...
...
c++/src/kj/vector.h
View file @
48547eb6
...
...
@@ -52,7 +52,8 @@ public:
inline
size_t
size
()
const
{
return
builder
.
size
();
}
inline
bool
empty
()
const
{
return
size
()
==
0
;
}
inline
size_t
capacity
()
const
{
return
builder
.
capacity
();
}
inline
T
&
operator
[](
size_t
index
)
const
{
return
builder
[
index
];
}
inline
T
&
operator
[](
size_t
index
)
{
return
builder
[
index
];
}
inline
const
T
&
operator
[](
size_t
index
)
const
{
return
builder
[
index
];
}
inline
const
T
*
begin
()
const
{
return
builder
.
begin
();
}
inline
const
T
*
end
()
const
{
return
builder
.
end
();
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment