Weird. It works with clang++ for me, modulo the clang bug we also ran into
here: https://github.com/sandstorm-io/sandstorm/pull/1450 .
I just tried compiling server.c++ with g++ version 6.1.1 and -std=c++14,
and I got the following error, which is puzzling (is it not actually legal
to call methods on a captured `this`?), but can be fixed by replacing
`pushEntryInternal(i - 1)` with `this->pushEntryInternal(i - 1)`:
server.c++:32:30: error: cannot call member function ‘void
EntryPusher::pushEntryInternal(int)’ without object
pushEntryInternal(i - 1);
However, the only way I was able to get the compiler to emit an error like
the one you're seeing was with the flag `std=c++11`.
Maybe you could work around the problem by explicitly writing out the type
of the parameter, rather than `auto x`. I think `capnp::Response<EntrySink::
ProcessResults> x` should work.
- David
On Tue, May 31, 2016 at 11:40 AM, Abhishek Balaji Radhakrishnan <
[email protected]> wrote:
> Tried that as well, but it doesn't work:
> c++ -std=c++1y -Wall entry_ss.c++ entry_protocol.capnp.c++ -pthread
> -I/usr/local/include -pthread -L/usr/local/lib -lcapnp-rpc -lcapnp
> -lkj-async -lkj -lpthread -o test_server
>
> Any workarounds to this?
>
> On Tue, May 31, 2016 at 11:32 AM, David Renshaw <[email protected]>
> wrote:
>
>> Are you compiling with c++14 features enabled? Usually the `-std=c++1y`
>> flag will do that.
>>
>> - David
>>
>>
>> On Tue, May 31, 2016 at 11:27 AM, Abhishek Balaji Radhakrishnan <
>> [email protected]> wrote:
>>
>>> Hi David and Kenton,
>>>
>>> I have a similar usecase for a project and I am trying to replicate this
>>> example to see how it works, but the server code in this case is throwing
>>> errors. Not sure what might have changed over time.
>>>
>>> A gist of the error is as follows:
>>> entry_ss.c++: In member function ‘void
>>> EntryPusher::pushEntryInternal(int)’:
>>> entry_ss.c++:29:53: error: parameter declared ‘auto’
>>> taskSet.add(entryReq.send().then([this, i](auto x) {
>>> ^
>>> entry_ss.c++: In lambda function:
>>> entry_ss.c++:34:69: error: parameter declared ‘auto’
>>> taskSet.add(processor.doneRequest().send().then([](auto x)
>>> {}));
>>> ^
>>> In file included from /usr/local/include/kj/async.h:29:0,
>>> from /usr/local/include/capnp/capability.h:33,
>>> from /usr/local/include/capnp/rpc.h:29,
>>> from /usr/local/include/capnp/ez-rpc.h:29,
>>> from entry_ss.c++:5:
>>>
>>> ...
>>>
>>>
>>> I see that the pushEntryInternal() is causing the problem with the
>>> then() semantics - not sure how to fix this:
>>>
>>> void pushEntryInternal(int i) {
>>> auto entryReq = processor.processRequest();
>>> entryReq.getEntry().setData(i);
>>> taskSet.add(entryReq.send().then([this, i](auto x) {
>>> usleep(500000);
>>> if (i > 0) {
>>> pushEntryInternal(i - 1);
>>> } else {
>>> taskSet.add(processor.doneRequest().send().then([](auto x)
>>> {}));
>>> }
>>> }));
>>> }
>>>
>>>
>>> Thanks,
>>> Abhishek
>>>
>>>
>>>
>>> On Tuesday, 21 October 2014 21:47:21 UTC-4, David Renshaw wrote:
>>>>
>>>> Ouch. Looks like `GC_apply_to_all_blocks()` doesn't give you any chance
>>>> to yield control. So though you can queue up as many sends as you like,
>>>> they won't get executed until `GC_apply_to_all_blocks()` completes. You'd
>>>> be better off just buffering the GCEntries in a list.
>>>>
>>>> If you don't want to buffer all of the GCEntry objects in memory before
>>>> sending them, then I think you're forced to put the call to
>>>> `GC_apply_to_all_blocks()` in a separate thread. You could communicate with
>>>> that thread using a socketpair, receiving the GCEntries back as a raw
>>>> stream of Cap'n Proto messages, and then forwarding the entries to the
>>>> `sendGCEntry()` method. The read methods declared in serialize-async.h
>>>> allow you to do this in a way that plays nicely with the event loop.
>>>>
>>>>
>>>> -David
>>>>
>>>>
>>>> On Tue, Oct 21, 2014 at 6:51 PM, Turing Eret <[email protected]>
>>>> wrote:
>>>>
>>>>> Easier to do in theory than practice. In my actual program, my
>>>>> equivalent of pushEntry() is this:
>>>>>
>>>>> void processMonoObjects(mono_object_processor f, void* user_data)
>>>>>
>>>>> {
>>>>>
>>>>> mono_gc_disable();
>>>>>
>>>>>
>>>>>
>>>>> MonoHeapProcessorState state;
>>>>>
>>>>>
>>>>>
>>>>> state.vtables = getAllVTables();
>>>>>
>>>>> state.processor = f;
>>>>>
>>>>> state.user_data = user_data;
>>>>>
>>>>>
>>>>>
>>>>> GC_apply_to_all_blocks(blockProcessor, (word)&state);
>>>>>
>>>>>
>>>>>
>>>>> mono_gc_enable();
>>>>>
>>>>> }
>>>>>
>>>>> where mono_object_processor is defined as this:
>>>>>
>>>>> typedef void (__cdecl *mono_object_processor)(MonoObject* obj, void*
>>>>> user_data);
>>>>>
>>>>>
>>>>> Now, my equivalent of pushEntryInternal() is one of those
>>>>> mono_object_processor functions and GC_apply_to_all_blocks() calls that
>>>>> function on all the blocks known by the GC. Unfortunately, that isn't
>>>>> something I wrote nor something I can change. I attempted this:
>>>>>
>>>>> void scrapHeapProcessor(MonoObject* obj, HeapScraper* heapScraperPtr)
>>>>>
>>>>> {
>>>>>
>>>>> heapScraperPtr->promise = heapScraperPtr->promise.then([=]()
>>>>>
>>>>> {
>>>>>
>>>>>
>>>>> heapScraperPtr->sendGCEntry(obj);
>>>>>
>>>>> });
>>>>>
>>>>> }
>>>>>
>>>>>
>>>>> void HeapScraper::startScraping()
>>>>>
>>>>> {
>>>>>
>>>>> processMonoObjects((mono_object_processor)scrapHeapProcessor, this
>>>>> );
>>>>>
>>>>> taskSet.add(std::move(promise));
>>>>>
>>>>> }
>>>>>
>>>>>
>>>>> Unfortunately, this exploded badly in a stack overflow. Is that what
>>>>> you were suggesting? Is there a better way to do this that doesn't explode
>>>>> in my face?
>>>>>
>>>>>
>>>>> Turing
>>>>>
>>>>> On Tuesday, 21 October 2014 15:57:02 UTC-6, David Renshaw wrote:
>>>>>
>>>>>>
>>>>>> On Tue, Oct 21, 2014 at 3:59 PM, Turing Eret <[email protected]>
>>>>>> wrote:
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> So, each top-level call of pushEntryInternal() descends through to
>>>>>>> its base case before going up to the next top-level call of
>>>>>>> pushEntryInternal(), a depth-first traversal of the tasks. Is there any
>>>>>>> way
>>>>>>> to do that easily?
>>>>>>>
>>>>>>
>>>>>>
>>>>>> To accomplish that, I would redefine `pushEntryInternal()` so that it
>>>>>> returns a `kj::Promise<void>`, to be fulfilled when all the entries have
>>>>>> been pushed. Then I would chain the calls to `pushEntryInternal()` using
>>>>>> the `then()` method.
>>>>>>
>>>>>>
>>>>>>> PS: On a completely unrelated note, is there a document somewhere
>>>>>>> showing what languages have plugins currently in development and who is
>>>>>>> working on the plugin?
>>>>>>>
>>>>>>
>>>>>> Yes: https://kentonv.github.io/capnproto/otherlang.html
>>>>>>
>>>>>>
>>>>>> -David
>>>>>>
>>>>>>
>>>>
>>
>
>
> --
> Abhishek
>
--
You received this message because you are subscribed to the Google Groups
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.