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] 
> <javascript:>> 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 
>>>
>>>
>

-- 
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.

Reply via email to