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
e2905da7
Commit
e2905da7
authored
Nov 26, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Test and fix embargoes.
parent
6b8b8c71
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
143 additions
and
75 deletions
+143
-75
capability.c++
c++/src/capnp/capability.c++
+19
-1
rpc-test.c++
c++/src/capnp/rpc-test.c++
+0
-0
rpc.c++
c++/src/capnp/rpc.c++
+0
-0
test-util.c++
c++/src/capnp/test-util.c++
+6
-0
test-util.h
c++/src/capnp/test-util.h
+2
-0
test.capnp
c++/src/capnp/test.capnp
+6
-1
async.c++
c++/src/kj/async.c++
+94
-70
async.h
c++/src/kj/async.h
+16
-3
No files found.
c++/src/capnp/capability.c++
View file @
e2905da7
...
@@ -207,7 +207,13 @@ class QueuedPipeline final: public PipelineHook, public kj::Refcounted {
...
@@ -207,7 +207,13 @@ class QueuedPipeline final: public PipelineHook, public kj::Refcounted {
public
:
public
:
QueuedPipeline
(
const
kj
::
EventLoop
&
loop
,
kj
::
Promise
<
kj
::
Own
<
const
PipelineHook
>>&&
promise
)
QueuedPipeline
(
const
kj
::
EventLoop
&
loop
,
kj
::
Promise
<
kj
::
Own
<
const
PipelineHook
>>&&
promise
)
:
loop
(
loop
),
:
loop
(
loop
),
promise
(
loop
.
fork
(
kj
::
mv
(
promise
)))
{}
promise
(
loop
.
fork
(
kj
::
mv
(
promise
))),
selfResolutionOp
(
loop
.
there
(
this
->
promise
.
addBranch
(),
[
this
](
kj
::
Own
<
const
PipelineHook
>&&
inner
)
{
*
redirect
.
lockExclusive
()
=
kj
::
mv
(
inner
);
}))
{
selfResolutionOp
.
eagerlyEvaluate
(
loop
);
}
kj
::
Own
<
const
PipelineHook
>
addRef
()
const
override
{
kj
::
Own
<
const
PipelineHook
>
addRef
()
const
override
{
return
kj
::
addRef
(
*
this
);
return
kj
::
addRef
(
*
this
);
...
@@ -226,6 +232,12 @@ public:
...
@@ -226,6 +232,12 @@ public:
private
:
private
:
const
kj
::
EventLoop
&
loop
;
const
kj
::
EventLoop
&
loop
;
kj
::
ForkedPromise
<
kj
::
Own
<
const
PipelineHook
>>
promise
;
kj
::
ForkedPromise
<
kj
::
Own
<
const
PipelineHook
>>
promise
;
kj
::
MutexGuarded
<
kj
::
Maybe
<
kj
::
Own
<
const
PipelineHook
>>>
redirect
;
// Once the promise resolves, this will become non-null and point to the underlying object.
kj
::
Promise
<
void
>
selfResolutionOp
;
// Represents the operation which will set `redirect` when possible.
};
};
class
QueuedClient
final
:
public
ClientHook
,
public
kj
::
Refcounted
{
class
QueuedClient
final
:
public
ClientHook
,
public
kj
::
Refcounted
{
...
@@ -371,12 +383,18 @@ private:
...
@@ -371,12 +383,18 @@ private:
};
};
kj
::
Own
<
const
ClientHook
>
QueuedPipeline
::
getPipelinedCap
(
kj
::
Array
<
PipelineOp
>&&
ops
)
const
{
kj
::
Own
<
const
ClientHook
>
QueuedPipeline
::
getPipelinedCap
(
kj
::
Array
<
PipelineOp
>&&
ops
)
const
{
auto
lock
=
redirect
.
lockShared
();
KJ_IF_MAYBE
(
redirect
,
*
lock
)
{
return
redirect
->
get
()
->
getPipelinedCap
(
kj
::
mv
(
ops
));
}
else
{
auto
clientPromise
=
loop
.
there
(
promise
.
addBranch
(),
kj
::
mvCapture
(
ops
,
auto
clientPromise
=
loop
.
there
(
promise
.
addBranch
(),
kj
::
mvCapture
(
ops
,
[](
kj
::
Array
<
PipelineOp
>&&
ops
,
kj
::
Own
<
const
PipelineHook
>
pipeline
)
{
[](
kj
::
Array
<
PipelineOp
>&&
ops
,
kj
::
Own
<
const
PipelineHook
>
pipeline
)
{
return
pipeline
->
getPipelinedCap
(
kj
::
mv
(
ops
));
return
pipeline
->
getPipelinedCap
(
kj
::
mv
(
ops
));
}));
}));
return
kj
::
refcounted
<
QueuedClient
>
(
loop
,
kj
::
mv
(
clientPromise
));
return
kj
::
refcounted
<
QueuedClient
>
(
loop
,
kj
::
mv
(
clientPromise
));
}
}
}
// =======================================================================================
// =======================================================================================
...
...
c++/src/capnp/rpc-test.c++
View file @
e2905da7
This diff is collapsed.
Click to expand it.
c++/src/capnp/rpc.c++
View file @
e2905da7
This diff is collapsed.
Click to expand it.
c++/src/capnp/test-util.c++
View file @
e2905da7
...
@@ -1052,5 +1052,11 @@ kj::Promise<void> TestMoreStuffImpl::getHeld(
...
@@ -1052,5 +1052,11 @@ kj::Promise<void> TestMoreStuffImpl::getHeld(
return
kj
::
READY_NOW
;
return
kj
::
READY_NOW
;
}
}
kj
::
Promise
<
void
>
TestMoreStuffImpl
::
echo
(
EchoParams
::
Reader
params
,
EchoResults
::
Builder
result
)
{
++
callCount
;
result
.
setCap
(
params
.
getCap
());
return
kj
::
READY_NOW
;
}
}
// namespace _ (private)
}
// namespace _ (private)
}
// namespace capnp
}
// namespace capnp
c++/src/capnp/test-util.h
View file @
e2905da7
...
@@ -237,6 +237,8 @@ public:
...
@@ -237,6 +237,8 @@ public:
kj
::
Promise
<
void
>
getHeld
(
GetHeldParams
::
Reader
params
,
kj
::
Promise
<
void
>
getHeld
(
GetHeldParams
::
Reader
params
,
GetHeldResults
::
Builder
result
)
override
;
GetHeldResults
::
Builder
result
)
override
;
kj
::
Promise
<
void
>
echo
(
EchoParams
::
Reader
params
,
EchoResults
::
Builder
result
)
override
;
private
:
private
:
int
&
callCount
;
int
&
callCount
;
kj
::
Own
<
kj
::
PromiseFulfiller
<
void
>>
neverFulfill
;
kj
::
Own
<
kj
::
PromiseFulfiller
<
void
>>
neverFulfill
;
...
...
c++/src/capnp/test.capnp
View file @
e2905da7
...
@@ -611,8 +611,10 @@ interface TestPipeline {
...
@@ -611,8 +611,10 @@ interface TestPipeline {
}
}
interface TestCallOrder {
interface TestCallOrder {
getCallSequence @0 () -> (n: UInt32);
getCallSequence @0 (
expected: UInt32
) -> (n: UInt32);
# First call returns 0, next returns 1, ...
# First call returns 0, next returns 1, ...
#
# The input `expected` is ignored but useful for disambiguating debug logs.
}
}
interface TestTailCallee {
interface TestTailCallee {
...
@@ -649,6 +651,9 @@ interface TestMoreStuff extends(TestCallOrder) {
...
@@ -649,6 +651,9 @@ interface TestMoreStuff extends(TestCallOrder) {
getHeld @5 () -> (cap :TestInterface);
getHeld @5 () -> (cap :TestInterface);
# Returns the capability previously held using `hold` (and keeps holding it).
# Returns the capability previously held using `hold` (and keeps holding it).
echo @6 (cap :TestCallOrder) -> (cap :TestCallOrder);
# Just returns the input cap.
}
}
struct TestSturdyRefHostId {
struct TestSturdyRefHostId {
...
...
c++/src/kj/async.c++
View file @
e2905da7
...
@@ -69,6 +69,91 @@ public:
...
@@ -69,6 +69,91 @@ public:
}
// namespace
}
// namespace
namespace
_
{
// private
class
TaskSetImpl
{
public
:
inline
TaskSetImpl
(
const
EventLoop
&
loop
,
TaskSet
::
ErrorHandler
&
errorHandler
)
:
loop
(
loop
),
errorHandler
(
errorHandler
)
{}
~
TaskSetImpl
()
noexcept
(
false
)
{
// std::map doesn't like it when elements' destructors throw, so carefully disassemble it.
auto
&
taskMap
=
tasks
.
getWithoutLock
();
if
(
!
taskMap
.
empty
())
{
Vector
<
Own
<
Task
>>
deleteMe
(
taskMap
.
size
());
for
(
auto
&
entry
:
taskMap
)
{
deleteMe
.
add
(
kj
::
mv
(
entry
.
second
));
}
}
}
class
Task
final
:
public
EventLoop
::
Event
{
public
:
Task
(
const
TaskSetImpl
&
taskSet
,
Own
<
_
::
PromiseNode
>&&
nodeParam
)
:
EventLoop
::
Event
(
taskSet
.
loop
),
taskSet
(
taskSet
),
node
(
kj
::
mv
(
nodeParam
))
{
if
(
node
->
onReady
(
*
this
))
{
arm
();
}
}
~
Task
()
{
disarm
();
}
protected
:
void
fire
()
override
{
// Get the result.
_
::
ExceptionOr
<
_
::
Void
>
result
;
node
->
get
(
result
);
// Delete the node, catching any exceptions.
KJ_IF_MAYBE
(
exception
,
kj
::
runCatchingExceptions
([
this
]()
{
node
=
nullptr
;
}))
{
result
.
addException
(
kj
::
mv
(
*
exception
));
}
// Call the error handler if there was an exception.
KJ_IF_MAYBE
(
e
,
result
.
exception
)
{
taskSet
.
errorHandler
.
taskFailed
(
kj
::
mv
(
*
e
));
}
}
private
:
const
TaskSetImpl
&
taskSet
;
kj
::
Own
<
_
::
PromiseNode
>
node
;
};
void
add
(
Promise
<
void
>&&
promise
)
const
{
auto
task
=
heap
<
Task
>
(
*
this
,
_
::
makeSafeForLoop
<
_
::
Void
>
(
kj
::
mv
(
promise
.
node
),
loop
));
Task
*
ptr
=
task
;
tasks
.
lockExclusive
()
->
insert
(
std
::
make_pair
(
ptr
,
kj
::
mv
(
task
)));
}
private
:
const
EventLoop
&
loop
;
TaskSet
::
ErrorHandler
&
errorHandler
;
// TODO(soon): Use a linked list instead. We should factor out the intrusive linked list code
// that appears in EventLoop and ForkHub.
MutexGuarded
<
std
::
map
<
Task
*
,
Own
<
Task
>>>
tasks
;
};
class
LoggingErrorHandler
:
public
TaskSet
::
ErrorHandler
{
public
:
static
LoggingErrorHandler
instance
;
void
taskFailed
(
kj
::
Exception
&&
exception
)
override
{
KJ_LOG
(
ERROR
,
"Uncaught exception in daemonized task."
,
exception
);
}
};
LoggingErrorHandler
LoggingErrorHandler
::
instance
=
LoggingErrorHandler
();
}
// namespace _ (private)
// =======================================================================================
EventLoop
&
EventLoop
::
current
()
{
EventLoop
&
EventLoop
::
current
()
{
EventLoop
*
result
=
threadLocalEventLoop
;
EventLoop
*
result
=
threadLocalEventLoop
;
KJ_REQUIRE
(
result
!=
nullptr
,
"No event loop is running on this thread."
);
KJ_REQUIRE
(
result
!=
nullptr
,
"No event loop is running on this thread."
);
...
@@ -79,7 +164,10 @@ bool EventLoop::isCurrent() const {
...
@@ -79,7 +164,10 @@ bool EventLoop::isCurrent() const {
return
threadLocalEventLoop
==
this
;
return
threadLocalEventLoop
==
this
;
}
}
EventLoop
::
EventLoop
()
{}
EventLoop
::
EventLoop
()
:
daemons
(
kj
::
heap
<
_
::
TaskSetImpl
>
(
*
this
,
_
::
LoggingErrorHandler
::
instance
))
{}
EventLoop
::~
EventLoop
()
noexcept
(
false
)
{}
void
EventLoop
::
waitImpl
(
Own
<
_
::
PromiseNode
>
node
,
_
::
ExceptionOrValue
&
result
)
{
void
EventLoop
::
waitImpl
(
Own
<
_
::
PromiseNode
>
node
,
_
::
ExceptionOrValue
&
result
)
{
EventLoop
*
oldEventLoop
=
threadLocalEventLoop
;
EventLoop
*
oldEventLoop
=
threadLocalEventLoop
;
...
@@ -119,6 +207,10 @@ void EventLoop::receivedNewJob() const {
...
@@ -119,6 +207,10 @@ void EventLoop::receivedNewJob() const {
wake
();
wake
();
}
}
void
EventLoop
::
daemonize
(
kj
::
Promise
<
void
>&&
promise
)
const
{
daemons
->
add
(
kj
::
mv
(
promise
));
}
EventLoop
::
Event
::
Event
(
const
EventLoop
&
loop
)
EventLoop
::
Event
::
Event
(
const
EventLoop
&
loop
)
:
loop
(
loop
),
:
loop
(
loop
),
jobs
{
loop
.
queue
.
createJob
(
*
this
),
loop
.
queue
.
createJob
(
*
this
)
}
{}
jobs
{
loop
.
queue
.
createJob
(
*
this
),
loop
.
queue
.
createJob
(
*
this
)
}
{}
...
@@ -227,76 +319,8 @@ void PromiseBase::absolve() {
...
@@ -227,76 +319,8 @@ void PromiseBase::absolve() {
runCatchingExceptions
([
this
]()
{
node
=
nullptr
;
});
runCatchingExceptions
([
this
]()
{
node
=
nullptr
;
});
}
}
class
TaskSet
::
Impl
{
public
:
inline
Impl
(
const
EventLoop
&
loop
,
ErrorHandler
&
errorHandler
)
:
loop
(
loop
),
errorHandler
(
errorHandler
)
{}
~
Impl
()
noexcept
(
false
)
{
// std::map doesn't like it when elements' destructors throw, so carefully disassemble it.
auto
&
taskMap
=
tasks
.
getWithoutLock
();
if
(
!
taskMap
.
empty
())
{
Vector
<
Own
<
Task
>>
deleteMe
(
taskMap
.
size
());
for
(
auto
&
entry
:
taskMap
)
{
deleteMe
.
add
(
kj
::
mv
(
entry
.
second
));
}
}
}
class
Task
final
:
public
EventLoop
::
Event
{
public
:
Task
(
const
Impl
&
taskSet
,
Own
<
_
::
PromiseNode
>&&
nodeParam
)
:
EventLoop
::
Event
(
taskSet
.
loop
),
taskSet
(
taskSet
),
node
(
kj
::
mv
(
nodeParam
))
{
if
(
node
->
onReady
(
*
this
))
{
arm
();
}
}
~
Task
()
{
disarm
();
}
protected
:
void
fire
()
override
{
// Get the result.
_
::
ExceptionOr
<
_
::
Void
>
result
;
node
->
get
(
result
);
// Delete the node, catching any exceptions.
KJ_IF_MAYBE
(
exception
,
runCatchingExceptions
([
this
]()
{
node
=
nullptr
;
}))
{
result
.
addException
(
kj
::
mv
(
*
exception
));
}
// Call the error handler if there was an exception.
KJ_IF_MAYBE
(
e
,
result
.
exception
)
{
taskSet
.
errorHandler
.
taskFailed
(
kj
::
mv
(
*
e
));
}
}
private
:
const
Impl
&
taskSet
;
kj
::
Own
<
_
::
PromiseNode
>
node
;
};
void
add
(
Promise
<
void
>&&
promise
)
const
{
auto
task
=
heap
<
Task
>
(
*
this
,
_
::
makeSafeForLoop
<
_
::
Void
>
(
kj
::
mv
(
promise
.
node
),
loop
));
Task
*
ptr
=
task
;
tasks
.
lockExclusive
()
->
insert
(
std
::
make_pair
(
ptr
,
kj
::
mv
(
task
)));
}
private
:
const
EventLoop
&
loop
;
ErrorHandler
&
errorHandler
;
// TODO(soon): Use a linked list instead. We should factor out the intrusive linked list code
// that appears in EventLoop and ForkHub.
MutexGuarded
<
std
::
map
<
Task
*
,
Own
<
Task
>>>
tasks
;
};
TaskSet
::
TaskSet
(
const
EventLoop
&
loop
,
ErrorHandler
&
errorHandler
)
TaskSet
::
TaskSet
(
const
EventLoop
&
loop
,
ErrorHandler
&
errorHandler
)
:
impl
(
heap
<
Impl
>
(
loop
,
errorHandler
))
{}
:
impl
(
heap
<
_
::
TaskSet
Impl
>
(
loop
,
errorHandler
))
{}
TaskSet
::~
TaskSet
()
noexcept
(
false
)
{}
TaskSet
::~
TaskSet
()
noexcept
(
false
)
{}
...
...
c++/src/kj/async.h
View file @
e2905da7
...
@@ -182,6 +182,8 @@ class ChainPromiseNode;
...
@@ -182,6 +182,8 @@ class ChainPromiseNode;
template
<
typename
T
>
template
<
typename
T
>
class
ForkHub
;
class
ForkHub
;
class
TaskSetImpl
;
}
// namespace _ (private)
}
// namespace _ (private)
// =======================================================================================
// =======================================================================================
...
@@ -228,6 +230,7 @@ class EventLoop: private _::NewJobCallback {
...
@@ -228,6 +230,7 @@ class EventLoop: private _::NewJobCallback {
public
:
public
:
EventLoop
();
EventLoop
();
~
EventLoop
()
noexcept
(
false
);
static
EventLoop
&
current
();
static
EventLoop
&
current
();
// Get the event loop for the current thread. Throws an exception if no event loop is active.
// Get the event loop for the current thread. Throws an exception if no event loop is active.
...
@@ -298,6 +301,15 @@ public:
...
@@ -298,6 +301,15 @@ public:
Promise
<
T
>
exclusiveJoin
(
Promise
<
T
>&&
promise1
,
Promise
<
T
>&&
promise2
)
const
;
Promise
<
T
>
exclusiveJoin
(
Promise
<
T
>&&
promise1
,
Promise
<
T
>&&
promise2
)
const
;
// Like `promise1.exclusiveJoin(promise2)`, returning the joined promise.
// Like `promise1.exclusiveJoin(promise2)`, returning the joined promise.
void
daemonize
(
kj
::
Promise
<
void
>&&
promise
)
const
;
// Allows the given promise to continue running in the background until it completes or the
// `EventLoop` is destroyed. Be careful when using this: you need to make sure that the promise
// owns all the objects it touches or make sure those objects outlive the EventLoop. Also, be
// careful about error handling: exceptions will merely be logged with KJ_LOG(ERROR, ...).
//
// This method exists mainly to implement the Cap'n Proto requirement that RPC calls cannot be
// canceled unless the callee explicitly permits it.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
// Low-level interface.
// Low-level interface.
...
@@ -387,6 +399,8 @@ private:
...
@@ -387,6 +399,8 @@ private:
Maybe
<
_
::
WorkQueue
<
EventJob
>::
JobWrapper
&>
insertionPoint
;
Maybe
<
_
::
WorkQueue
<
EventJob
>::
JobWrapper
&>
insertionPoint
;
// Where to insert preemptively-scheduled events into the queue.
// Where to insert preemptively-scheduled events into the queue.
Own
<
_
::
TaskSetImpl
>
daemons
;
template
<
typename
T
,
typename
Func
,
typename
ErrorFunc
>
template
<
typename
T
,
typename
Func
,
typename
ErrorFunc
>
Own
<
_
::
PromiseNode
>
thereImpl
(
Promise
<
T
>&&
promise
,
Func
&&
func
,
ErrorFunc
&&
errorHandler
)
const
;
Own
<
_
::
PromiseNode
>
thereImpl
(
Promise
<
T
>&&
promise
,
Func
&&
func
,
ErrorFunc
&&
errorHandler
)
const
;
// Shared implementation of there() and Promise::then().
// Shared implementation of there() and Promise::then().
...
@@ -456,7 +470,7 @@ private:
...
@@ -456,7 +470,7 @@ private:
friend
class
_
::
ChainPromiseNode
;
friend
class
_
::
ChainPromiseNode
;
template
<
typename
>
template
<
typename
>
friend
class
Promise
;
friend
class
Promise
;
friend
class
TaskSet
;
friend
class
_
::
TaskSetImpl
;
};
};
template
<
typename
T
>
template
<
typename
T
>
...
@@ -763,8 +777,7 @@ public:
...
@@ -763,8 +777,7 @@ public:
void
add
(
Promise
<
void
>&&
promise
)
const
;
void
add
(
Promise
<
void
>&&
promise
)
const
;
private
:
private
:
class
Impl
;
Own
<
_
::
TaskSetImpl
>
impl
;
Own
<
Impl
>
impl
;
};
};
constexpr
_
::
Void
READY_NOW
=
_
::
Void
();
constexpr
_
::
Void
READY_NOW
=
_
::
Void
();
...
...
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