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
4802eee2
Commit
4802eee2
authored
Apr 01, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Doc proof-read.
parent
db57d130
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
178 additions
and
87 deletions
+178
-87
page.html
doc/_layouts/page.html
+15
-6
cxx.md
doc/cxx.md
+22
-19
encoding.md
doc/encoding.md
+45
-21
install.md
doc/install.md
+62
-14
language.md
doc/language.md
+21
-18
stylesheet.css
doc/stylesheets/stylesheet.css
+13
-9
No files found.
doc/_layouts/page.html
View file @
4802eee2
...
@@ -59,15 +59,21 @@
...
@@ -59,15 +59,21 @@
var
menu
=
document
.
getElementById
(
"menu"
);
var
menu
=
document
.
getElementById
(
"menu"
);
var
setMenuLayout
=
function
()
{
var
setMenuLayout
=
function
()
{
if
(
window
.
innerWidth
<
117
0
)
{
if
(
window
.
innerWidth
<
90
0
)
{
document
.
body
.
className
=
"narrow"
;
document
.
body
.
className
=
"narrow"
;
menu
.
className
=
""
;
menu
.
className
=
""
;
}
else
if
(
window
.
scrollY
<
219
||
window
.
innerHeight
<
menu
.
clientHeight
+
20
)
{
document
.
body
.
className
=
"wide"
;
menu
.
className
=
""
;
}
else
{
}
else
{
document
.
body
.
className
=
"wide"
;
if
(
window
.
innerWidth
<
1170
)
{
menu
.
className
=
"floating"
;
document
.
body
.
className
=
"normal"
;
}
else
{
document
.
body
.
className
=
"wide"
;
}
if
(
window
.
scrollY
<
219
||
window
.
innerHeight
<
menu
.
clientHeight
+
20
)
{
menu
.
className
=
""
;
}
else
{
menu
.
className
=
"floating"
;
}
}
}
};
};
setMenuLayout
();
setMenuLayout
();
...
@@ -166,6 +172,9 @@
...
@@ -166,6 +172,9 @@
parent
.
appendChild
(
item
);
parent
.
appendChild
(
item
);
}
}
}
}
var
menu
=
document
.
getElementById
(
"menu"
);
document
.
getElementById
(
"main_content"
).
style
.
minHeight
=
menu
.
clientHeight
+
100
+
"px"
;
})()
})()
</script>
</script>
...
...
doc/cxx.md
View file @
4802eee2
...
@@ -64,18 +64,17 @@ void printAddressBook(int fd) {
...
@@ -64,18 +64,17 @@ void printAddressBook(int fd) {
This implementation makes use of C++11 features. If you are using GCC, you will need at least
This implementation makes use of C++11 features. If you are using GCC, you will need at least
version 4.7 to compile Cap'n Proto, with
`--std=gnu++0x`
. Other compilers have not been tested at
version 4.7 to compile Cap'n Proto, with
`--std=gnu++0x`
. Other compilers have not been tested at
this time. In general, you do not need to understand C++11 features to _use_ Cap'n Proto; it all
this time.
happens under the hood.
This implementation prefers to handle errors using exceptions. Exceptions are only used in
This implementation prefers to handle errors using exceptions. Exceptions are only used in
circumstances that should never occur in normal opertaion. For example, exceptions are thrown
circumstances that should never occur in normal opertaion. For example, exceptions are thrown
on assertion failures (indicating bugs in the code), network failures
(indicating incorrect
on assertion failures (indicating bugs in the code), network failures
, and invalid input.
configuration), and invalid input. Exceptions thrown by Cap'n Proto are never part of the
Exceptions thrown by Cap'n Proto are never part of the interface and never need to be caught in
interface and never need to be caught in correct usage. The purpose of throwing exceptions is
to
correct usage. The purpose of throwing exceptions is to allow higher-level code a chance
to
allow higher-level code a chance to recover from unexpected circumstances without disrupting other
recover from unexpected circumstances without disrupting other work happening in the same process.
work happening in the same process. For example, a server that handles requests from multiple
For example, a server that handles requests from multiple clients should, on exception, return an
clients should, on exception, return an error to the client that caused the exception and clos
e
error to the client that caused the exception and close that connection, but should continu
e
that connection, but should continue
handling other connections normally.
handling other connections normally.
When Cap'n Proto code might throw an exception from a destructor, it first checks
When Cap'n Proto code might throw an exception from a destructor, it first checks
`std::uncaught_exception()`
to ensure that this is safe. If another exception is already active,
`std::uncaught_exception()`
to ensure that this is safe. If another exception is already active,
...
@@ -86,7 +85,7 @@ In recognition of the fact that some teams prefer not to use exceptions, and tha
...
@@ -86,7 +85,7 @@ In recognition of the fact that some teams prefer not to use exceptions, and tha
exceptions in the compiler introduces overhead, Cap'n Proto allows you to disable them entirely
exceptions in the compiler introduces overhead, Cap'n Proto allows you to disable them entirely
by registering your own exception callback. The callback will be called in place of throwing an
by registering your own exception callback. The callback will be called in place of throwing an
exception. The callback may abort the process, and is required to do so in certain circumstances
exception. The callback may abort the process, and is required to do so in certain circumstances
(
e.g.
when a fatal bug is detected). If the callback returns normally, Cap'n Proto will attempt
(when a fatal bug is detected). If the callback returns normally, Cap'n Proto will attempt
to continue by inventing "safe" values. This will lead to garbage output, but at least the program
to continue by inventing "safe" values. This will lead to garbage output, but at least the program
will not crash. Your exception callback should set some sort of a flag indicating that an error
will not crash. Your exception callback should set some sort of a flag indicating that an error
occurred, and somewhere up the stack you should check for that flag and cancel the operation.
occurred, and somewhere up the stack you should check for that flag and cancel the operation.
...
@@ -100,6 +99,7 @@ To generate C++ code from your `.capnp` [interface definition](language.html), r
...
@@ -100,6 +99,7 @@ To generate C++ code from your `.capnp` [interface definition](language.html), r
capnpc myproto.capnp
capnpc myproto.capnp
This will create
`myproto.capnp.h`
and
`myproto.capnp.c++`
in the same directory as
`myproto.capnp`
.
This will create
`myproto.capnp.h`
and
`myproto.capnp.c++`
in the same directory as
`myproto.capnp`
.
(Currently, it also dumps some debug info to stdout, e.g. the offset of each field.)
_TODO: This will become more complicated later as we add support for more languages and such._
_TODO: This will become more complicated later as we add support for more languages and such._
...
@@ -149,11 +149,11 @@ MyStruct::Reader getMyStructField();
...
@@ -149,11 +149,11 @@ MyStruct::Reader getMyStructField();
`Foo::Builder`
, meanwhile, has two or three methods for each field
`bar`
:
`Foo::Builder`
, meanwhile, has two or three methods for each field
`bar`
:
*
`getBar()`
: For primitives, returns the value. For composites, returns a Builder for the
*
`getBar()`
: For primitives, returns the value. For composites, returns a Builder for the
composite. If a composite field has not been initialized (i
ts pointer is null), it will be
composite. If a composite field has not been initialized (i
.e. this is the first time it has
initialized to a copy of the field's default value before returning.
been accessed), it will be
initialized to a copy of the field's default value before returning.
*
`setBar(x)`
: For primitives, sets the value to X. For composites, sets the value to a copy of
*
`setBar(x)`
: For primitives, sets the value to X. For composites, sets the value to a copy of
x, which must be a Reader for the type.
x, which must be a Reader for the type.
*
`initBar(n)`
: Only for lists
(including blobs). Sets the field to a newly-allocated list
*
`initBar(n)`
: Only for lists
and blobs. Sets the field to a newly-allocated list or blob
of size n and returns a Builder for it. The elements of the list are initialized to their empty
of size n and returns a Builder for it. The elements of the list are initialized to their empty
state (zero for numbers, default values for structs).
state (zero for numbers, default values for structs).
*
`initBar()`
: Only for structs. Sets the field to a newly-allocated struct and returns a
*
`initBar()`
: Only for structs. Sets the field to a newly-allocated struct and returns a
...
@@ -190,7 +190,8 @@ void setMyListField(::capnproto::List<double>::Reader value);
...
@@ -190,7 +190,8 @@ void setMyListField(::capnproto::List<double>::Reader value);
## Lists
## Lists
Lists are represented by the type
`capnproto::List<T>`
, where
`T`
is any of the primitive types,
Lists are represented by the type
`capnproto::List<T>`
, where
`T`
is any of the primitive types,
any Cap'n Proto user-defined type,
`capnproto::Text`
,
`capnproto::Data`
, or
`capnproto::List<T>`
.
any Cap'n Proto user-defined type,
`capnproto::Text`
,
`capnproto::Data`
, or
`capnproto::List<U>`
(to form a list of lists).
The type
`List<T>`
itself is not instantiatable, but has two inner classes:
`Reader`
and
`Builder`
.
The type
`List<T>`
itself is not instantiatable, but has two inner classes:
`Reader`
and
`Builder`
.
As with structs, these types behave like pointers to read-only and read-write data, respectively.
As with structs, these types behave like pointers to read-only and read-write data, respectively.
...
@@ -213,16 +214,18 @@ values when the list is created.
...
@@ -213,16 +214,18 @@ values when the list is created.
## Enums
## Enums
Cap'n Proto enums become C++11 "enum classes". That means
,
they behave like any other enum, but
Cap'n Proto enums become C++11 "enum classes". That means they behave like any other enum, but
the enum's values are scoped within the type. E.g. for an enum
`Foo`
with value
`bar`
, you must
the enum's values are scoped within the type. E.g. for an enum
`Foo`
with value
`bar`
, you must
refer to the value as
`Foo::BAR`
.
The enum class's base type is
`uint16_t`
.
refer to the value as
`Foo::BAR`
.
To match prevaling C++ style, an enum's value names are converted to UPPERCASE_WITH_UNDERSCORES
To match prevaling C++ style, an enum's value names are converted to UPPERCASE_WITH_UNDERSCORES
(whereas in the definition language you'd write them in camelCase).
(whereas in the definition language you'd write them in camelCase).
Keep in mind when writing
`switch`
blocks that an enum read off the wire may have a numeric
Keep in mind when writing
`switch`
blocks that an enum read off the wire may have a numeric
value that is not listed in its definition. This may be the case if the sender is using a newer
value that is not listed in its definition. This may be the case if the sender is using a newer
version of the protocol, or if the message is corrupt or malicious.
version of the protocol, or if the message is corrupt or malicious. In C++11, enums are allowed
to have any value that is within the range of their base type, which for Cap'n Proto enums is
`uint16_t`
.
## Blobs (Text and Data)
## Blobs (Text and Data)
...
@@ -252,11 +255,11 @@ Interfaces (RPC) are not yet implemented at this time.
...
@@ -252,11 +255,11 @@ Interfaces (RPC) are not yet implemented at this time.
To create a new message, you must start by creating a
`capnproto::MessageBuilder`
To create a new message, you must start by creating a
`capnproto::MessageBuilder`
(
`capnproto/message.h`
). This is an abstract type which you can implement yourself, but most users
(
`capnproto/message.h`
). This is an abstract type which you can implement yourself, but most users
will want to use
`capnproto::MallocMessageBuilder`
. Once your message is constructed, write it to
will want to use
`capnproto::MallocMessageBuilder`
. Once your message is constructed, write it to
a file descriptor
`capnproto::writeMessageToFd(fd, builder)`
(
`capnproto/serialize.h`
) or
a file descriptor
with
`capnproto::writeMessageToFd(fd, builder)`
(
`capnproto/serialize.h`
) or
`capnproto::writePackedMessageToFd(fd, builder)`
(
`capnproto/serialize-packed.h`
).
`capnproto::writePackedMessageToFd(fd, builder)`
(
`capnproto/serialize-packed.h`
).
To read a message, you must create a
`capnproto::MessageReader`
, which is another abstract type.
To read a message, you must create a
`capnproto::MessageReader`
, which is another abstract type.
Implementations are specific to the
import
source. You can use
`capnproto::StreamFdMessageReader`
Implementations are specific to the
data
source. You can use
`capnproto::StreamFdMessageReader`
(
`capnproto/serialize.h`
) or
`capnproto::PackedFdMessageReader`
(
`capnproto/serialize-packed.h`
)
(
`capnproto/serialize.h`
) or
`capnproto::PackedFdMessageReader`
(
`capnproto/serialize-packed.h`
)
to read from file descriptors; both take the file descriptor as a constructor argument.
to read from file descriptors; both take the file descriptor as a constructor argument.
...
...
doc/encoding.md
View file @
4802eee2
...
@@ -12,8 +12,8 @@ by this spec is newer than what is actually implemented.
...
@@ -12,8 +12,8 @@ by this spec is newer than what is actually implemented.
## 64-bit Words
## 64-bit Words
For the purpose of Cap'n Proto, a "word" is defined as 8 bytes, or 64 bits. Since alignment of
For the purpose of Cap'n Proto, a "word" is defined as 8 bytes, or 64 bits. Since alignment of
data is important, all objects
are aligned to word boundaries, and sizes are usually expressed in
data is important, all objects
(structs, lists, and blobs) are aligned to word boundaries, and
terms of words.
sizes are usually expressed in
terms of words.
## Messages
## Messages
...
@@ -39,9 +39,6 @@ a message into multiple segments may be convenient:
...
@@ -39,9 +39,6 @@ a message into multiple segments may be convenient:
The first word of the first segment of the message is always a pointer pointing to the message's
The first word of the first segment of the message is always a pointer pointing to the message's
root struct.
root struct.
Note that users of Cap'n Proto never need to understand segments; this is all taken care of
automatically by the runtime library.
## Built-in Types
## Built-in Types
The built-in primitive types are encoded as follows:
The built-in primitive types are encoded as follows:
...
@@ -59,11 +56,13 @@ The built-in blob types are encoded as follows:
...
@@ -59,11 +56,13 @@ The built-in blob types are encoded as follows:
*
`Data`
: Encoded as a pointer, identical to
`List(UInt8)`
.
*
`Data`
: Encoded as a pointer, identical to
`List(UInt8)`
.
*
`Text`
: Like
`Data`
, but the content must be valid UTF-8, the last byte of the content must be
*
`Text`
: Like
`Data`
, but the content must be valid UTF-8, the last byte of the content must be
zero, and no other byte of the content can be zero.
zero, and no other byte of the content can be zero. Note that the NUL terminator is included in
the size sent on the wire, but the runtime library should not count it in any size reported to
the application.
## Enums
## Enums
Enums are encoded the same as
16-bit integers
.
Enums are encoded the same as
`UInt16`
.
## Lists
## Lists
...
@@ -74,9 +73,9 @@ A list value is encoded as a pointer to a flat array of values.
...
@@ -74,9 +73,9 @@ A list value is encoded as a pointer to a flat array of values.
|A| B |C | D |
|A| B |C | D |
+-+-----------------------------+--+----------------------------+
+-+-----------------------------+--+----------------------------+
A (2 bits) =
0
1, to indicate that this is a list pointer.
A (2 bits) = 1, to indicate that this is a list pointer.
B (30 bits) = Offset, in words, from the start of the pointer to the
B (30 bits) = Offset, in words, from the start of the pointer to the
start of the list. Signed.
start of the
first element of the
list. Signed.
C (3 bits) = Size of each element:
C (3 bits) = Size of each element:
0 = 0 (e.g. List(Void))
0 = 0 (e.g. List(Void))
1 = 1 bit
1 = 1 bit
...
@@ -120,7 +119,7 @@ A struct pointer looks like this:
...
@@ -120,7 +119,7 @@ A struct pointer looks like this:
|A| B | C | D |
|A| B | C | D |
+-+-----------------------------+---------------+---------------+
+-+-----------------------------+---------------+---------------+
A (2 bits) = 0
0
, to indicate that this is a struct pointer.
A (2 bits) = 0, to indicate that this is a struct pointer.
B (30 bits) = Offset, in words, from the start of the pointer to the
B (30 bits) = Offset, in words, from the start of the pointer to the
start of the struct's data section. Signed.
start of the struct's data section. Signed.
C (16 bits) = Size of the struct's data section, in words.
C (16 bits) = Size of the struct's data section, in words.
...
@@ -133,8 +132,8 @@ Ignoring unions, the layout of fields within the struct is determined by the fol
...
@@ -133,8 +132,8 @@ Ignoring unions, the layout of fields within the struct is determined by the fol
For each field of the struct, ordered by field number {
For each field of the struct, ordered by field number {
If the field is a pointer {
If the field is a pointer {
Add it to the end of the pointer section.
Add it to the end of the pointer section.
} else if the data section layout so far includes p
adding large
} else if the data section layout so far includes p
roperly-aligned
enough and properly-aligned
to hold this field {
padding large enough
to hold this field {
Replace the padding space with the new field, preferring to
Replace the padding space with the new field, preferring to
put the field as close to the beginning of the section as
put the field as close to the beginning of the section as
possible.
possible.
...
@@ -165,14 +164,15 @@ When unions are present, add the following logic:
...
@@ -165,14 +164,15 @@ When unions are present, add the following logic:
member at all. (See no-union logic, above.)
member at all. (See no-union logic, above.)
}
}
} else {
} else {
Treat it as a regular field
. (See no-union logic, above.)
Assign an offset as normal
. (See no-union logic, above.)
}
}
}
}
Note that in the worst case, the members of a union could end up using 23 bytes plus one bit (one
Note that in the worst case, the members of a union could end up using 23 bytes plus one bit (one
pointer plus data section locations of 64, 32, 16, 8, and 1 bits). This is an unfortunate side
pointer plus data section locations of 64, 32, 16, 8, and 1 bits). This is an unfortunate side
effect of the desire to pack fields in the smallest space where they will fit and the need to
effect of the desire to pack fields in the smallest space where they will fit and the need to
maintain backwards-compatibility as fields are added. The worst case should be rare in practice.
maintain backwards-compatibility as fields are added. The worst case should be rare in practice,
and can be avoided entirely by always declaring a union's largest member first.
### Default Values
### Default Values
...
@@ -201,7 +201,7 @@ the pointer as a "far pointer", which looks like this:
...
@@ -201,7 +201,7 @@ the pointer as a "far pointer", which looks like this:
|A| B | C |
|A| B | C |
+-+-----------------------------+-------------------------------+
+-+-----------------------------+-------------------------------+
A (2 bits) =
0
2, to indicate that this is a far pointer.
A (2 bits) = 2, to indicate that this is a far pointer.
B (30 bits) = Offset, in words, from the start of the target segment
B (30 bits) = Offset, in words, from the start of the target segment
to the location of the far-pointer landing-pad within that
to the location of the far-pointer landing-pad within that
segment.
segment.
...
@@ -221,14 +221,14 @@ The reason for the convoluted double-far convention is to make it possible to fo
...
@@ -221,14 +221,14 @@ The reason for the convoluted double-far convention is to make it possible to fo
to an object in a segment that is full. If you can't allocate even one word in the segment where
to an object in a segment that is full. If you can't allocate even one word in the segment where
the target resides, then you will need to allocate a landing pad in some other segment, and use
the target resides, then you will need to allocate a landing pad in some other segment, and use
this double-far approach. This should be exceedingly rare in practice since pointers are normally
this double-far approach. This should be exceedingly rare in practice since pointers are normally
set to point to
_new_ object
s.
set to point to
new objects, not existing one
s.
## Serialization Over a Stream
## Serialization Over a Stream
When transmitting a message, the segments must be framed in some way, i.e. to communicate the
When transmitting a message, the segments must be framed in some way, i.e. to communicate the
number of segments and their sizes before communicating the actual data. The best framing approach
number of segments and their sizes before communicating the actual data. The best framing approach
may differ depending on the medium -- for example, messages read via
`mmap`
or shared memory may
may differ depending on the medium -- for example, messages read via
`mmap`
or shared memory may
call for different approach than messages sent over a socket or a pipe. Cap'n Proto does not
call for
a
different approach than messages sent over a socket or a pipe. Cap'n Proto does not
attempt to specify a framing format for every situation. However, since byte streams are by far
attempt to specify a framing format for every situation. However, since byte streams are by far
the most common transmission medium, Cap'n Proto does define and implement a recommended framing
the most common transmission medium, Cap'n Proto does define and implement a recommended framing
format for them.
format for them.
...
@@ -238,7 +238,7 @@ little-endian.
...
@@ -238,7 +238,7 @@ little-endian.
*
(4 bytes) The number of segments, minus one (since there is always at least one segment).
*
(4 bytes) The number of segments, minus one (since there is always at least one segment).
*
(N
*
4 bytes) The size of each segment, in words.
*
(N
*
4 bytes) The size of each segment, in words.
*
(0 or 4 bytes) Padding up to
a multiple of words
.
*
(0 or 4 bytes) Padding up to
the next word boundary
.
*
The content of each segment, in order.
*
The content of each segment, in order.
## Packing
## Packing
...
@@ -271,9 +271,33 @@ In addition to the above, there are two tag values which are treated specially:
...
@@ -271,9 +271,33 @@ In addition to the above, there are two tag values which are treated specially:
long text blobs. Because of this rule, the worst-case space overhead of packing is 2 bytes per
long text blobs. Because of this rule, the worst-case space overhead of packing is 2 bytes per
2 KiB of input (256 words = 2KiB).
2 KiB of input (256 words = 2KiB).
Packing is normally applied on top of the standard stream framing described in the previous
section.
## Compression
## Compression
When Cap'n Proto messages may contain repetitive data (especially, large text blobs), it makes sense
When Cap'n Proto messages may contain repetitive data (especially, large text blobs), it makes sense
to apply a standard compression algorithm in addition to packing. When CPU time is also still
to apply a standard compression algorithm in addition to packing. When CPU time is scarce, we
important, we recommend Google's
[
Snappy
](
https://code.google.com/p/snappy/
)
. Otherwise,
recommend Google's
[
Snappy
](
https://code.google.com/p/snappy/
)
. Otherwise,
[
zlib
](
http://www.zlib.net
)
is probably a good choice.
[
zlib
](
http://www.zlib.net
)
is slower but will compress more.
## Security Notes
A naive implementation of a Cap'n Proto reader may be vulnerable to DoS attacks based on two types
of malicious input:
*
A message containing cyclic (or even just overlapping) pointers can cause the reader to go into
an infinite loop while traversing the content.
*
A message with deeply-nested objects can cause a stack overflow in typical code which processes
messages recursively.
To defend against these attacks, every Cap'n Proto implementation should implemented the following
restrictions by default:
*
As the application traverses the message, each time a pointer is dereferenced, a counter should
be incremented by the size of the data to which it points. If this counter goes over some limit,
an error should be raised, and/or default values should be returned. The C++ implementation
currently defaults to a limit of 64MiB, but allows the caller to set a different limit if desired.
*
As the application traverses the message, the pointer depth should be tracked. Again, if it goes
over some limit, an error should be raised. The C++ implementation currently defaults to a limit
of 64 pointers, but allows the caller to set a different limit.
doc/install.md
View file @
4802eee2
...
@@ -65,7 +65,7 @@ productivity, so I really like using Ekam.
...
@@ -65,7 +65,7 @@ productivity, so I really like using Ekam.
Unfortunately it's very much unfinished. It works (for me), but it is quirky and rough around the
Unfortunately it's very much unfinished. It works (for me), but it is quirky and rough around the
edges. It only works on Linux, and is best used together with Eclipse. If you find it
edges. It only works on Linux, and is best used together with Eclipse. If you find it
unacceptable, scroll down to the
Automake instructions, below
.
unacceptable, scroll down to the
[
Automake instructions
](
#building_with_automake
)
.
The Cap'n Proto repo includes a script which will attempt to set up Ekam for you.
The Cap'n Proto repo includes a script which will attempt to set up Ekam for you.
...
@@ -79,18 +79,61 @@ symlinks under src. It also imports the [Google Test](https://googletest.google
...
@@ -79,18 +79,61 @@ symlinks under src. It also imports the [Google Test](https://googletest.google
Once Ekam is installed, you can do:
Once Ekam is installed, you can do:
make -f Makefile.ekam
continuous
make -f Makefile.ekam
once
This will build everything it can and run tests. If successful, the benchmarks will be built
This will build everything it can and run tests.
and saved in
`tmp/capnproto/benchmark`
. Try running
`tmp/capnproto/benchmark/runner`
.
Note that Ekam will fail to build some things and output a bunch of error messages. You should
Note that Ekam will fail to build some things and output a bunch of error messages. You should
be able to ignore any errors that originate outside of the
`capnproto`
directory -- these are just
be able to ignore any errors that originate outside of the
`capnproto`
directory -- these are just
parts of other packages like Google Test that Ekam doesn't fully know how to build, but aren't
parts of other packages like Google Test that Ekam doesn't fully know how to build, but aren't
needed by Cap'n Proto anyway.
needed by Cap'n Proto anyway.
### Running the Benchmarks
Before getting into benchmarks, let me be frank: performance varies wildly by use case, and no
benchmark is going to properly reflect the big picture. If performance is critical to your use
case, you should write a benchmark specific to your case, and test multiple serialization
technologies. Don't assume anything. If you find Cap'n Proto performs sub-optimally, though,
[
tell us about it
](
https://groups.google.com/group/capnproto
)
.
That said, Cap'n Proto does have a small suite of silly benchmarks used to validate changes.
The Ekam build will put the benchmark binaries in
`tmp/capnproto/benchmark`
.
tmp/capnproto/benchmark
This runs the default test case, CatRank. CatRank simulates a search engine scoring algorithm
which promotes pages that discuss cats (and demotes ones discussing dogs). A list of up to 1000
random search results with URLs, scores, and snippets is sent to the server, which searches the
snippets for instances of "cat" and "dog", adjusts their scores accordingly, then returns the new
result list sorted by score.
This test case is very string-heavy. Cap'n Proto performs well due to its zero-copy strings, but
packing the message doesn't help much.
tmp/capnproto/benchmark eval
In this test case, the client generates a random, deeply-nested arithmetic expression for the
server to evaluate. This case is a pathologically bad case for Cap'n Proto as it involves lots of
pointers with relatively little actual data. When packing is enabled it actually loses to
Protobufs by a little bit on CPU time (as of this writing, at least; it'll probably get better with
optimization).
tmp/capnproto/benchmark carsales
This test case involves sending to the server a description of a bunch of cars, and asks the server
to decide how much the lot is worth. This case is very number-heavy, and because of this
Cap'n Proto's "packed" mode really shines.
### Developing with Ekam
If you intend to do some development, you should build
`continuous`
or
`continuous-opt`
instead
of
`once`
. These modes will build everything, then watch the source tree for changes and rebuild
as necessary.
`continuous`
does a debug build while
`continuous-opt`
optimizes; the former is best
while developing but don't run the benchmarks in debug mode!
If you use Eclipse, you should use the Ekam Eclipse plugin to get build results fed back into your
If you use Eclipse, you should use the Ekam Eclipse plugin to get build results fed back into your
editor. Build the plugin like so:
editor
while building in continuous mode
. Build the plugin like so:
1.
Open the
`.ekam/eclipse`
directory as an Eclipse project.
1.
Open the
`.ekam/eclipse`
directory as an Eclipse project.
2.
File -> Export -> Plug-in Development -> Deployable Plug-ins and Fragments.
2.
File -> Export -> Plug-in Development -> Deployable Plug-ins and Fragments.
...
@@ -102,10 +145,10 @@ editor. Build the plugin like so:
...
@@ -102,10 +145,10 @@ editor. Build the plugin like so:
within this project.
within this project.
6.
Window -> Show View -> Other -> Ekam -> Ekam Dashboard
6.
Window -> Show View -> Other -> Ekam -> Ekam Dashboard
The dashboard view lets you browse the whole tree
and also populates your editor with err
or
The dashboard view lets you browse the whole tree
of build actions and also populates your edit
or
markers.
with error
markers.
### Building
W
ith Automake
### Building
w
ith Automake
If setting up Ekam is too much work for you, you can also build with Automake.
If setting up Ekam is too much work for you, you can also build with Automake.
...
@@ -117,17 +160,22 @@ If setting up Ekam is too much work for you, you can also build with Automake.
...
@@ -117,17 +160,22 @@ If setting up Ekam is too much work for you, you can also build with Automake.
unzip gtest-1.6.0.zip
unzip gtest-1.6.0.zip
cd gtest-1.6.0
cd gtest-1.6.0
./configure
./configure
make
make -j4
cp -r include/gtest $PREFIX/include/gtest
mkdir -p ~/gtest-install/include
cp ./lib/.libs/*.a $PREFIX/lib
mkdir -p ~/gtest-install/lib
cp -r include/gtest ~/gtest-install/include/gtest
cp ./lib/.libs/*.a ~/gtest-install/lib
2.
Clone and build the Cap'n Proto code.
2.
Clone and build the Cap'n Proto code.
git clone https://github.com/kentonv/capnproto.git
git clone https://github.com/kentonv/capnproto.git
cd capnproto/c++
cd capnproto/c++
autoreconf -i
autoreconf -i
./configure
CXXFLAGS="-O2 -DNDEBUG -I$HOME/gtest-install/include" \
make check
LDFLAGS="-L$HOME/gtest-install/lib" \
./configure
make -j4 check
sudo make install
sudo make install
This will install libcapnproto.a in /usr/local/lib and headers in /usr/local/include/capnproto.
This will install
`libcapnproto.a`
in
`/usr/local/lib`
and headers in
`/usr/local/include/capnproto`
.
doc/language.md
View file @
4802eee2
...
@@ -40,9 +40,8 @@ struct Date {
...
@@ -40,9 +40,8 @@ struct Date {
Some notes:
Some notes:
*
Types come after names. This makes sense because the name is usually the thing you are looking
*
Types come after names. The name is by far the most important thing to see, especially when
for when you read the code, so it should be up front where it is easiest to see, not hidden later
quickly skimming, so we put it up front where it is most visible. Sorry, C got it wrong.
on the line. Sorry, C got it wrong.
*
The
`@N`
annotations show how the protocol evolved over time, so that the system can make sure
*
The
`@N`
annotations show how the protocol evolved over time, so that the system can make sure
to maintain compatibility with older versions. Fields (and enum values, and interface methods)
to maintain compatibility with older versions. Fields (and enum values, and interface methods)
must be numbered consecutively starting from zero in the order in which they were added. In this
must be numbered consecutively starting from zero in the order in which they were added. In this
...
@@ -95,7 +94,7 @@ The following types are automatically defined:
...
@@ -95,7 +94,7 @@ The following types are automatically defined:
Notes:
Notes:
*
The
`Void`
type has exactly one possible value, and thus can be encoded in zero b
yte
s. It is
*
The
`Void`
type has exactly one possible value, and thus can be encoded in zero b
it
s. It is
rarely used, but can be useful as a union member.
rarely used, but can be useful as a union member.
*
`Text`
is always UTF-8 encoded and NUL-terminated.
*
`Text`
is always UTF-8 encoded and NUL-terminated.
*
`Data`
is a completely arbitrary sequence of bytes.
*
`Data`
is a completely arbitrary sequence of bytes.
...
@@ -142,6 +141,7 @@ struct Person {
...
@@ -142,6 +141,7 @@ struct Person {
employer @6 in employment :Company;
employer @6 in employment :Company;
school @7 in employment :School;
school @7 in employment :School;
selfEmployed @8 in employment :Void;
selfEmployed @8 in employment :Void;
# We assume that a person is only one of these.
}
}
{% endhighlight %}
{% endhighlight %}
...
@@ -149,12 +149,13 @@ Notes:
...
@@ -149,12 +149,13 @@ Notes:
*
Unions are numbered in the same number space as other fields. Remember that the purpose of the
*
Unions are numbered in the same number space as other fields. Remember that the purpose of the
numbers is to indicate the evolution order of the struct. The system needs to know when the union
numbers is to indicate the evolution order of the struct. The system needs to know when the union
was declared relative to the fields in it. Also note that
at most
one element of the union is
was declared relative to the fields in it. Also note that
no more than
one element of the union is
allowed to have a number less than the union's number, as unionizing two or more
existing fields
allowed to have a number less than the union's number, as unionizing two or more
pre-existing
would change their layout.
fields
would change their layout.
*
Notice that we used the "useless"
`Void`
type here. We don't have any extra information to store
*
Notice that we used the "useless"
`Void`
type here. We don't have any extra information to store
for the
`unemployed`
or
`selfEmployed`
cases, but we still want the union to have tags for them.
for the
`unemployed`
or
`selfEmployed`
cases, but we still want the union to distinguish these
states from others.
### Enums
### Enums
...
@@ -204,7 +205,7 @@ interface File {
...
@@ -204,7 +205,7 @@ interface File {
{% endhighlight %}
{% endhighlight %}
Notice something interesting here:
`FileInfo`
is a struct, but it contains a
`File`
, which is an
Notice something interesting here:
`FileInfo`
is a struct, but it contains a
`File`
, which is an
interface. Structs (and primitive types) are passed by value, but interfaces are passed by
interface. Structs (and primitive types) are passed
over RPC
by value, but interfaces are passed by
reference. So when
`Directory.open`
is called remotely, the content of a
`FileInfo`
(including
reference. So when
`Directory.open`
is called remotely, the content of a
`FileInfo`
(including
values for
`name`
and
`size`
) is transmitted back, but for the
`file`
field, only the address of
values for
`name`
and
`size`
) is transmitted back, but for the
`file`
field, only the address of
some remote
`File`
object is sent.
some remote
`File`
object is sent.
...
@@ -218,7 +219,8 @@ reference to an object inherently represents a "capability" to access it.
...
@@ -218,7 +219,8 @@ reference to an object inherently represents a "capability" to access it.
### Constants
### Constants
You can define constants in Cap'n Proto. Constants can have any value.
You can define constants in Cap'n Proto. These don't affect what is sent on the wire, but they
will be included in the generated code.
{% highlight capnp %}
{% highlight capnp %}
const pi :Float32 = 3.14159;
const pi :Float32 = 3.14159;
...
@@ -237,11 +239,11 @@ struct Foo {
...
@@ -237,11 +239,11 @@ struct Foo {
struct Bar {
struct Bar {
#...
#...
}
}
bar@0 :Bar;
bar
@0 :Bar;
}
}
struct Baz {
struct Baz {
bar@0 :Foo.Bar;
bar
@0 :Foo.Bar;
}
}
{% endhighlight %}
{% endhighlight %}
...
@@ -250,12 +252,12 @@ If typing long scopes becomes cumbersome, you can use `using` to declare an alia
...
@@ -250,12 +252,12 @@ If typing long scopes becomes cumbersome, you can use `using` to declare an alia
{% highlight capnp %}
{% highlight capnp %}
struct Qux {
struct Qux {
using Foo.Bar;
using Foo.Bar;
bar@0 :Bar;
bar
@0 :Bar;
}
}
struct Corge {
struct Corge {
using T = Foo.Bar;
using T = Foo.Bar;
bar@0 :T;
bar
@0 :T;
}
}
{% endhighlight %}
{% endhighlight %}
...
@@ -266,7 +268,7 @@ An `import` expression names the scope of some other file:
...
@@ -266,7 +268,7 @@ An `import` expression names the scope of some other file:
{% highlight capnp %}
{% highlight capnp %}
struct Foo {
struct Foo {
# Use type "Baz" defined in bar.capnp.
# Use type "Baz" defined in bar.capnp.
baz@0 :import "bar.capnp".Baz;
baz
@0 :import "bar.capnp".Baz;
}
}
{% endhighlight %}
{% endhighlight %}
...
@@ -277,7 +279,7 @@ using Bar = import "bar.capnp";
...
@@ -277,7 +279,7 @@ using Bar = import "bar.capnp";
struct Foo {
struct Foo {
# Use type "Baz" defined in bar.capnp.
# Use type "Baz" defined in bar.capnp.
baz@0 :Bar.Baz;
baz
@0 :Bar.Baz;
}
}
{% endhighlight %}
{% endhighlight %}
...
@@ -302,10 +304,11 @@ A protocol can be changed in the following ways without breaking backwards-compa
...
@@ -302,10 +304,11 @@ A protocol can be changed in the following ways without breaking backwards-compa
*
New parameters may be added to a method. The new parameters must be added to the end of the
*
New parameters may be added to a method. The new parameters must be added to the end of the
parameter list and must have default values.
parameter list and must have default values.
*
Any symbolic name can be changed, as long as the ordinal numbers stay the same.
*
Any symbolic name can be changed, as long as the ordinal numbers stay the same.
*
Types definitions can be moved to different scopes.
*
A field of type
`List(T)`
, where
`T`
is NOT a struct type, may be changed to type
`List(U)`
,
*
A field of type
`List(T)`
, where
`T`
is NOT a struct type, may be changed to type
`List(U)`
,
where
`U`
is a struct type whose
field number 0
is of type
`T`
. This rule is useful when you
where
`U`
is a struct type whose
`@0`
field
is of type
`T`
. This rule is useful when you
realize too late that you need to attach some extra data to each element of your list. Without
realize too late that you need to attach some extra data to each element of your list. Without
this rule, you would be stuck defining parallel lists, which are ugly.
this rule, you would be stuck defining parallel lists, which are ugly
and error-prone
.
Any other change should be assumed NOT to be safe. Also, these rules only apply to the Cap'n Proto
Any other change should be assumed NOT to be safe. Also, these rules only apply to the Cap'n Proto
native encoding. It is sometimes useful to transcode Cap'n Proto types to other formats, like
native encoding. It is sometimes useful to transcode Cap'n Proto types to other formats, like
...
...
doc/stylesheets/stylesheet.css
View file @
4802eee2
...
@@ -279,6 +279,10 @@ Full-Width Styles
...
@@ -279,6 +279,10 @@ Full-Width Styles
margin
:
0
auto
;
margin
:
0
auto
;
}
}
body
.normal
#main_content
.inner
{
margin
:
0
auto
0
250px
;
}
#discuss_banner
{
#discuss_banner
{
display
:
block
;
display
:
block
;
position
:
absolute
;
position
:
absolute
;
...
@@ -481,7 +485,7 @@ Small Device Styles
...
@@ -481,7 +485,7 @@ Small Device Styles
}
}
.wide
#corner_hack
{
body
.wide
#corner_hack
,
body
.normal
#corner_hack
{
position
:
absolute
;
position
:
absolute
;
left
:
0px
;
left
:
0px
;
top
:
209px
;
top
:
209px
;
...
@@ -490,7 +494,7 @@ Small Device Styles
...
@@ -490,7 +494,7 @@ Small Device Styles
background
:
#212121
;
background
:
#212121
;
}
}
.wide
#corner_hack
>
div
{
body
.wide
#corner_hack
>
div
,
body
.normal
#corner_hack
>
div
{
margin-left
:
249px
;
margin-left
:
249px
;
height
:
10px
;
height
:
10px
;
border-radius
:
10px
0px
0px
0px
;
border-radius
:
10px
0px
0px
0px
;
...
@@ -499,7 +503,7 @@ Small Device Styles
...
@@ -499,7 +503,7 @@ Small Device Styles
border-left
:
1px
solid
#111
;
border-left
:
1px
solid
#111
;
}
}
.wide
#menu
{
body
.wide
#menu
,
body
.normal
#menu
{
position
:
absolute
;
position
:
absolute
;
left
:
0px
;
left
:
0px
;
top
:
219px
;
top
:
219px
;
...
@@ -507,12 +511,12 @@ Small Device Styles
...
@@ -507,12 +511,12 @@ Small Device Styles
z-index
:
10
;
z-index
:
10
;
}
}
.wide
#menu
.floating
{
body
.wide
#menu
.floating
,
body
.normal
#menu
.floating
{
position
:
fixed
;
position
:
fixed
;
top
:
0px
;
top
:
0px
;
}
}
.narrow
#menu
{
body
.narrow
#menu
{
position
:
relative
;
position
:
relative
;
max-width
:
640px
;
max-width
:
640px
;
padding
:
50px
10px
0px
10px
;
padding
:
50px
10px
0px
10px
;
...
@@ -520,7 +524,7 @@ Small Device Styles
...
@@ -520,7 +524,7 @@ Small Device Styles
}
}
@media
screen
and
(
max-width
:
480px
)
{
@media
screen
and
(
max-width
:
480px
)
{
.narrow
#menu
{
body
.narrow
#menu
{
min-width
:
320px
;
min-width
:
320px
;
max-width
:
480px
;
max-width
:
480px
;
}
}
...
@@ -541,16 +545,16 @@ Small Device Styles
...
@@ -541,16 +545,16 @@ Small Device Styles
border-right
:
1px
solid
#111
;
border-right
:
1px
solid
#111
;
}
}
.wide
#menu
>
ul
>
li
:last-child
{
body
.wide
#menu
>
ul
>
li
:last-child
,
body
.normal
#menu
>
ul
>
li
:last-child
{
border-radius
:
0px
0px
10px
0px
;
border-radius
:
0px
0px
10px
0px
;
border-bottom
:
1px
solid
#111
;
border-bottom
:
1px
solid
#111
;
}
}
.narrow
#menu
>
ul
>
li
:first-child
{
body
.narrow
#menu
>
ul
>
li
:first-child
{
border-radius
:
10px
10px
0px
0px
;
border-radius
:
10px
10px
0px
0px
;
}
}
.narrow
#menu
>
ul
>
li
:last-child
{
body
.narrow
#menu
>
ul
>
li
:last-child
{
border-radius
:
0px
0px
10px
10px
;
border-radius
:
0px
0px
10px
10px
;
}
}
...
...
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