<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Type erasure &#x2F; Asynchroner Callback]]></title><description><![CDATA[<p>Hi!<br />
Ich habe folgendes Szenario: Ein Puffer wird asynchron mit Daten befüllt. Sobald die Operation fertig ist, soll ein Callback in irgendeinem Thread aufgerufen werden, der als Parameter den Puffer enthält. Es versteht sich von selbst, dass der Puffer während der Operation gültig bleiben muss, Stack-Speicher entfällt also.</p>
<p>Jetzt will ich natürlich jede Form von manueller Speicherverwaltung vermeiden, weshalb ich mir sowas vorstelle:</p>
<pre><code class="language-cpp">void callback(buffer);

vector&lt;uint8_t&gt; buffer(1024);
start_operation(move(buffer), callback); // user muss sich nicht mehr um Lifetime von buffer kümmern

/* ... */
// irgendwo in der Library, wenn die Operation fertig ist:
callback(move(buffer)); // gib Puffer an Nutzer zurück (per Move-Konstruktor)

void callback(buffer b) { /* ... */ }
</code></pre>
<p>Mein Problem: wie bekomme ich das generisch (mit Templates/allgemeinen Typen) hin? Wenn die Operation abgeschlossen ist, habe ich prinipiell nur einen Pointer auf den Puffer (bzw. auf ein Objekt, welches den Puffer dann beinhaltet), der Typ ist verloren. Die Typen-Information rette ich mir mit virtual-Funktionen, also dispatche damit unterschiedliche Operations-Typen (lesen/schreiben/abbrechen etc.). Aber kann ich auch irgendwie das Typen-System von C++ benutzen, um die Template-Parameter mitzunehmen? Wenn ich das alles nicht manuell machen will, fällt mir spontan nur noch RTTI, also typeid ein.</p>
<p>Hat jemand einen Tipp?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/332811/type-erasure-asynchroner-callback</link><generator>RSS for Node</generator><lastBuildDate>Mon, 27 Apr 2026 12:03:22 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/332811.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 23 May 2015 14:09:38 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 14:10:47 GMT]]></title><description><![CDATA[<p>Hi!<br />
Ich habe folgendes Szenario: Ein Puffer wird asynchron mit Daten befüllt. Sobald die Operation fertig ist, soll ein Callback in irgendeinem Thread aufgerufen werden, der als Parameter den Puffer enthält. Es versteht sich von selbst, dass der Puffer während der Operation gültig bleiben muss, Stack-Speicher entfällt also.</p>
<p>Jetzt will ich natürlich jede Form von manueller Speicherverwaltung vermeiden, weshalb ich mir sowas vorstelle:</p>
<pre><code class="language-cpp">void callback(buffer);

vector&lt;uint8_t&gt; buffer(1024);
start_operation(move(buffer), callback); // user muss sich nicht mehr um Lifetime von buffer kümmern

/* ... */
// irgendwo in der Library, wenn die Operation fertig ist:
callback(move(buffer)); // gib Puffer an Nutzer zurück (per Move-Konstruktor)

void callback(buffer b) { /* ... */ }
</code></pre>
<p>Mein Problem: wie bekomme ich das generisch (mit Templates/allgemeinen Typen) hin? Wenn die Operation abgeschlossen ist, habe ich prinipiell nur einen Pointer auf den Puffer (bzw. auf ein Objekt, welches den Puffer dann beinhaltet), der Typ ist verloren. Die Typen-Information rette ich mir mit virtual-Funktionen, also dispatche damit unterschiedliche Operations-Typen (lesen/schreiben/abbrechen etc.). Aber kann ich auch irgendwie das Typen-System von C++ benutzen, um die Template-Parameter mitzunehmen? Wenn ich das alles nicht manuell machen will, fällt mir spontan nur noch RTTI, also typeid ein.</p>
<p>Hat jemand einen Tipp?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454524</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454524</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 23 May 2015 14:10:47 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 14:46:03 GMT]]></title><description><![CDATA[<p>Etwas ausführlicheres Beispiel:</p>
<pre><code class="language-cpp">void start_read_operation(buffer&amp;&amp; b, callback_function callback) {
    unique_ptr&lt;operation&gt; new_operation(new read_operation(b, callback)); // Polymorph!
    new_operation-&gt;start();
    new_operation.release();
}

// Callback-Thread:
void callback_thread() {
   while(1) {
      operation* op = wait_for_operation_to_complete();
      unique_ptr&lt;operation&gt; op_ptr(op); // RAII
      op-&gt;callback(std::move(op-&gt;buffer)); // Hier weiß ich nicht mehr, ob es eine read/write/whatever Operation ist, aber callback ist virtuell
   }
}
</code></pre>
<p>Jetzt will ich aber ein Funktionstemplate benutzen:</p>
<pre><code class="language-cpp">template &lt;typename BufferType&gt;
void start_read_operation(BufferType&amp;&amp; buffer, callback_function callback) { /* ... */ }
</code></pre>
<p>Und genau da hapert's, da ich den Typ irgendwie dynamisch kodieren muss.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454529</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454529</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 23 May 2015 14:46:03 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 16:15:19 GMT]]></title><description><![CDATA[<p>Kannste nicht beim virtual Dispatch in operation nicht direkt start_read_operation aufrufen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454540</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454540</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Sat, 23 May 2015 16:15:19 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 16:47:55 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>Kannste nicht beim virtual Dispatch in operation nicht direkt start_read_operation aufrufen?</p>
</blockquote>
<p>Wie meinst du das? <code>operation::callback</code> wird erst aufgerufen, nachdem irgendwann die Operation fertig ist, die mit <code>start_read_operation()</code> begonnen wurde.</p>
<p>Die Funktion <code>wait_for_operation_to_complete()</code> wartet eben so lange, bis irgendeine Operation fertig ist (egal ob read/write/bla). Aber an der Stelle kenne ich den Typ der Operation nicht mehr, deshalb virtual. Aber jetzt müsste operation ja auch ein Template werden, um den Buffer-Type zu generalisieren. Nur wie rette ich diesen Typen über die Laufzeit?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454549</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454549</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 23 May 2015 16:47:55 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 17:27:51 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">class operation
{
public:
    virtual void invoke_callback() = 0;
    // ...
};

template &lt;class BufferType, class CallbackType&gt;
class operation_impl : public operation
{
public:
    operation_impl(BufferType&amp;&amp; buffer, CallbackType&amp;&amp; callback)
        : m_buffer(move(buffer)),
        m_callback(move(callback))
    {
    }

    virtual void invoke_callback()
    {
        m_callback(move(m_buffer));
    }

private:
    CallbackType m_callback;
    BufferType m_buffer;
};

template &lt;class BufferType, class CallbackType&gt;
class read_operation : public operation_impl&lt;BufferType, CallbackType&gt;
{
public:
    // ...
};

void callback_thread()
{ 
    while (true)
    { 
       unique_ptr&lt;operation&gt; op(wait_for_operation_to_complete());
       op-&gt;invoke_callback();
    } 
}
</code></pre>
<p>?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454554</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454554</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 23 May 2015 17:27:51 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 17:33:40 GMT]]></title><description><![CDATA[<p>Wow danke, das probiere ich mal aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454556</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454556</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 23 May 2015 17:33:40 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 18:21:48 GMT]]></title><description><![CDATA[<p>Warum benutzt du eine Universal-Referenz für das Callback-Objekt? Kann man bei Sachen wie Funktionszeigern/Funktoren etc. nicht davon ausgehen, dass die billig zu kopieren sind?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454563</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454563</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 23 May 2015 18:21:48 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 18:26:10 GMT]]></title><description><![CDATA[<p>Oops, war ein Fehler.<br />
Ist auch keine Universal-Reference sondern eine R-Value Reference (ist ja kein Funktionstemplate).</p>
<p>Mach einfach <code>CallbackType const&amp;</code> draus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454564</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454564</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 23 May 2015 18:26:10 GMT</pubDate></item><item><title><![CDATA[Reply to Type erasure &#x2F; Asynchroner Callback on Sat, 23 May 2015 20:39:25 GMT]]></title><description><![CDATA[<p>Okay, es funktioniert wunderbar! Danke nochmal.</p>
<p>Edit: Nicht vergessen, einen virtual-Destruktor hinzuzufügen!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454570</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454570</guid><dc:creator><![CDATA[Jodocus]]></dc:creator><pubDate>Sat, 23 May 2015 20:39:25 GMT</pubDate></item></channel></rss>