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
d080e158
Commit
d080e158
authored
Nov 19, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Define Question/Answer/Import/Export nested so we can avoid the silly templates.
parent
f4ab3d2d
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
82 additions
and
78 deletions
+82
-78
rpc.c++
c++/src/capnp/rpc.c++
+82
-78
No files found.
c++/src/capnp/rpc.c++
View file @
d080e158
...
...
@@ -130,9 +130,6 @@ void fromException(const kj::Exception& exception, rpc::Exception::Builder build
// =======================================================================================
typedef
uint32_t
QuestionId
;
typedef
uint32_t
ExportId
;
template
<
typename
Id
,
typename
T
>
class
ExportTable
{
// Table mapping integers to T, where the integers are chosen locally.
...
...
@@ -230,69 +227,6 @@ private:
std
::
unordered_map
<
Id
,
T
>
high
;
};
template
<
typename
ParamCaps
,
typename
RpcPipeline
,
typename
RpcResponse
>
struct
Question
{
kj
::
Own
<
kj
::
PromiseFulfiller
<
kj
::
Own
<
RpcResponse
>>>
fulfiller
;
// Fulfill with the response.
kj
::
Maybe
<
kj
::
Own
<
ParamCaps
>>
paramCaps
;
// CapInjector from the parameter struct. This will be released once the `Return` message is
// received and `retainedCaps` processed. (If this is non-null, then the call has not returned
// yet.)
bool
isStarted
=
false
;
// Is this Question ID currently in-use? (This is true until both `Return` has been received and
// `Finish` has been sent.)
bool
isFinished
=
false
;
// Has the `Finish` message been sent?
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
!
isStarted
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
isStarted
;
}
};
template
<
typename
CallContext
>
struct
Answer
{
bool
active
=
false
;
// True from the point when the Call message is received to the point when both the `Finish`
// message has been received and the `Return` has been sent.
kj
::
Maybe
<
kj
::
Own
<
const
PipelineHook
>>
pipeline
;
// Send pipelined calls here. Becomes null as soon as a `Finish` is received.
kj
::
Promise
<
void
>
asyncOp
=
kj
::
Promise
<
void
>
(
nullptr
);
// Delete this promise to cancel the call.
kj
::
Maybe
<
const
CallContext
&>
callContext
;
// The call context, if it's still active. Becomes null when the `Return` message is sent. This
// object, if non-null, is owned by `asyncOp`.
};
struct
Export
{
uint
refcount
=
0
;
// When this reaches 0, drop `clientHook` and free this export.
kj
::
Own
<
const
ClientHook
>
clientHook
;
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
refcount
==
0
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
refcount
!=
0
;
}
};
template
<
typename
ImportClient
>
struct
Import
{
Import
()
=
default
;
Import
(
const
Import
&
)
=
delete
;
Import
(
Import
&&
)
=
default
;
Import
&
operator
=
(
Import
&&
)
=
default
;
// If we don't explicitly write all this, we get some stupid error deep in STL.
kj
::
Maybe
<
ImportClient
&>
client
;
// Becomes null when the import is destroyed.
kj
::
Maybe
<
kj
::
Own
<
kj
::
PromiseFulfiller
<
kj
::
Own
<
const
ClientHook
>>>>
promiseFulfiller
;
// If non-null, the import is a promise.
};
// =======================================================================================
class
RpcConnectionState
final
:
public
kj
::
TaskSet
::
ErrorHandler
,
public
kj
::
Refcounted
{
...
...
@@ -368,15 +302,14 @@ public:
__FILE__
,
__LINE__
,
kj
::
str
(
"Disconnected: "
,
exception
.
getDescription
()));
// All current questions complete with exceptions.
lock
->
questions
.
forEach
([
&
](
QuestionId
id
,
Question
<
CapInjectorImpl
,
RpcPipeline
,
RpcResponse
>&
question
)
{
lock
->
questions
.
forEach
([
&
](
QuestionId
id
,
Question
&
question
)
{
question
.
fulfiller
->
reject
(
kj
::
cp
(
networkException
));
KJ_IF_MAYBE
(
pc
,
question
.
paramCaps
)
{
paramCapsToRelease
.
add
(
kj
::
mv
(
*
pc
));
}
});
lock
->
answers
.
forEach
([
&
](
QuestionId
id
,
Answer
<
RpcCallContext
>
&
answer
)
{
lock
->
answers
.
forEach
([
&
](
QuestionId
id
,
Answer
&
answer
)
{
KJ_IF_MAYBE
(
p
,
answer
.
pipeline
)
{
pipelinesToRelease
.
add
(
kj
::
mv
(
*
p
));
}
...
...
@@ -391,7 +324,7 @@ public:
exp
=
Export
();
});
lock
->
imports
.
forEach
([
&
](
ExportId
id
,
Import
<
ImportClient
>
&
import
)
{
lock
->
imports
.
forEach
([
&
](
ExportId
id
,
Import
&
import
)
{
KJ_IF_MAYBE
(
f
,
import
.
promiseFulfiller
)
{
f
->
get
()
->
reject
(
kj
::
cp
(
networkException
));
}
...
...
@@ -414,11 +347,6 @@ public:
}
private
:
const
kj
::
EventLoop
&
eventLoop
;
kj
::
Maybe
<
SturdyRefRestorerBase
&>
restorer
;
kj
::
Own
<
VatNetworkBase
::
Connection
>
connection
;
kj
::
Own
<
kj
::
PromiseFulfiller
<
void
>>
disconnectFulfiller
;
class
ImportClient
;
class
PromiseClient
;
class
CapInjectorImpl
;
...
...
@@ -427,11 +355,87 @@ private:
class
RpcCallContext
;
class
RpcResponse
;
// =======================================================================================
// The Four Tables entry types
//
// We have to define these before we can define the class's fields.
typedef
uint32_t
QuestionId
;
typedef
uint32_t
ExportId
;
struct
Question
{
kj
::
Own
<
kj
::
PromiseFulfiller
<
kj
::
Own
<
RpcResponse
>>>
fulfiller
;
// Fulfill with the response.
kj
::
Maybe
<
kj
::
Own
<
CapInjectorImpl
>>
paramCaps
;
// CapInjector from the parameter struct. This will be released once the `Return` message is
// received and `retainedCaps` processed. (If this is non-null, then the call has not returned
// yet.)
bool
isStarted
=
false
;
// Is this Question ID currently in-use? (This is true until both `Return` has been received and
// `Finish` has been sent.)
bool
isFinished
=
false
;
// Has the `Finish` message been sent?
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
!
isStarted
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
isStarted
;
}
};
struct
Answer
{
bool
active
=
false
;
// True from the point when the Call message is received to the point when both the `Finish`
// message has been received and the `Return` has been sent.
kj
::
Maybe
<
kj
::
Own
<
const
PipelineHook
>>
pipeline
;
// Send pipelined calls here. Becomes null as soon as a `Finish` is received.
kj
::
Promise
<
void
>
asyncOp
=
kj
::
Promise
<
void
>
(
nullptr
);
// Delete this promise to cancel the call.
kj
::
Maybe
<
const
RpcCallContext
&>
callContext
;
// The call context, if it's still active. Becomes null when the `Return` message is sent. This
// object, if non-null, is owned by `asyncOp`.
};
struct
Export
{
uint
refcount
=
0
;
// When this reaches 0, drop `clientHook` and free this export.
kj
::
Own
<
const
ClientHook
>
clientHook
;
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
refcount
==
0
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
refcount
!=
0
;
}
};
struct
Import
{
Import
()
=
default
;
Import
(
const
Import
&
)
=
delete
;
Import
(
Import
&&
)
=
default
;
Import
&
operator
=
(
Import
&&
)
=
default
;
// If we don't explicitly write all this, we get some stupid error deep in STL.
kj
::
Maybe
<
ImportClient
&>
client
;
// Becomes null when the import is destroyed.
kj
::
Maybe
<
kj
::
Own
<
kj
::
PromiseFulfiller
<
kj
::
Own
<
const
ClientHook
>>>>
promiseFulfiller
;
// If non-null, the import is a promise.
};
// =======================================================================================
// OK, now we can define RpcConnectionState's member data.
const
kj
::
EventLoop
&
eventLoop
;
kj
::
Maybe
<
SturdyRefRestorerBase
&>
restorer
;
kj
::
Own
<
VatNetworkBase
::
Connection
>
connection
;
kj
::
Own
<
kj
::
PromiseFulfiller
<
void
>>
disconnectFulfiller
;
struct
Tables
{
ExportTable
<
ExportId
,
Export
>
exports
;
ExportTable
<
QuestionId
,
Question
<
CapInjectorImpl
,
RpcPipeline
,
RpcResponse
>
>
questions
;
ImportTable
<
QuestionId
,
Answer
<
RpcCallContext
>
>
answers
;
ImportTable
<
ExportId
,
Import
<
ImportClient
>
>
imports
;
ExportTable
<
QuestionId
,
Question
>
questions
;
ImportTable
<
QuestionId
,
Answer
>
answers
;
ImportTable
<
ExportId
,
Import
>
imports
;
// The order of the tables is important for correct destruction.
std
::
unordered_map
<
const
ClientHook
*
,
ExportId
>
exportsByCap
;
...
...
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