<?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[Asynchrone Callbacks&#x2F;Buffer-Ownership]]></title><description><![CDATA[<p>Hallo.<br />
Angenommen, ich kann ein paar asynchrone Eingabe-/Ausgabe-Tasks durchführen, welche Daten aus einem Puffer (Array) lesen bzw. schreiben, die dann einen Callback aufrufen, wenn sie fertig sind.<br />
Während die Operation noch läuft, müssen die Puffer gültig bleiben. Beispiel:</p>
<pre><code class="language-cpp">void callback(buffer&amp; b) { ... } // wird irgendwann in anderem Thread aufgerufen

void foo() {
    buffer b;
    start_operation(callback, std::move(b)); // move gut?
</code></pre>
<p>Wie sollte der Besitz von b hier geregelt werden?<br />
Möglichkeiten, die mir einfallen, sind:</p>
<p>1. Nutzer erstellt Puffer und behält Ownership auch während der Operation, muss also gewährleisten, dass der Puffer gültig bleibt.</p>
<p>Der Vorteil, den ich hier denke ich bekomme, ist, dass der Nutzer den Puffer befüllen und manipulieren kann und er nicht kopiert werden muss, da die Operation dann quasi nur eine Referenz/Zeiger auf den Puffer hat.<br />
Nachteil: Der Nutzer muss daran denken, alles richtig zu machen. Fatal wäre dann z.B.</p>
<pre><code class="language-cpp">void foo() {
   buffer b; // auf dem Stack!
   start_operation(callback, b); // call by reference für b
} // b.~buffer() :(
</code></pre>
<p>Bessere Lösung wäre wohl</p>
<pre><code class="language-cpp">void callback(buffer*);

void foo() {
   auto bptr = make_unique&lt;buffer&gt;(); // wegen Exceptions etc.
   start_operation(callback, bptr.get());
   bptr.release(); // damit buffer gültig bleibt, kann aber leicht vergessen werden :(
}

void callback(buffer* b) {
   unique_ptr&lt;buffer&gt; bptr(b); // wieder Exception-safety + RAII
   ...
}
</code></pre>
<p>So mache ich es momentan, hier kann aber so viel vergessen werden. Aber das ist so viel manuelle Speicherverwaltung. Deswegen suche ich Alternativen.</p>
<p>2. Nutzer hat niemals Besitz am Puffer und die Library kümmert sich drum, also</p>
<pre><code class="language-cpp">void callback(buffer&amp; b) { ... } // nur Referenz, nachdem callback durch ist wird buffer gelöscht

void foo() {
   start_operation(callback, 50); // 50 Bytes Puffer
}
</code></pre>
<p>Vorteil: Viel weniger manuelle Verwaltung.<br />
Nachteil: Nutzer muss Puffer im Callback manuell kopieren, wenn er mit den Daten noch etwas anfangen will.</p>
<p>3. Besitz hin und her reichen:</p>
<pre><code class="language-cpp">void callback(buffer b) { ... }

void foo() {
   buffer b;
   start_operation(callback, std::move(b)); // irgendwann wird dann callback(std::move(b)) aufgerufen
}
</code></pre>
<p>Hat das irgendwelche Nachteile?<br />
Was würdet ihr machen?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/332263/asynchrone-callbacks-buffer-ownership</link><generator>RSS for Node</generator><lastBuildDate>Tue, 28 Apr 2026 10:56:52 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/332263.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 18 Apr 2015 14:52:16 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Asynchrone Callbacks&#x2F;Buffer-Ownership on Sat, 18 Apr 2015 14:52:16 GMT]]></title><description><![CDATA[<p>Hallo.<br />
Angenommen, ich kann ein paar asynchrone Eingabe-/Ausgabe-Tasks durchführen, welche Daten aus einem Puffer (Array) lesen bzw. schreiben, die dann einen Callback aufrufen, wenn sie fertig sind.<br />
Während die Operation noch läuft, müssen die Puffer gültig bleiben. Beispiel:</p>
<pre><code class="language-cpp">void callback(buffer&amp; b) { ... } // wird irgendwann in anderem Thread aufgerufen

void foo() {
    buffer b;
    start_operation(callback, std::move(b)); // move gut?
</code></pre>
<p>Wie sollte der Besitz von b hier geregelt werden?<br />
Möglichkeiten, die mir einfallen, sind:</p>
<p>1. Nutzer erstellt Puffer und behält Ownership auch während der Operation, muss also gewährleisten, dass der Puffer gültig bleibt.</p>
<p>Der Vorteil, den ich hier denke ich bekomme, ist, dass der Nutzer den Puffer befüllen und manipulieren kann und er nicht kopiert werden muss, da die Operation dann quasi nur eine Referenz/Zeiger auf den Puffer hat.<br />
Nachteil: Der Nutzer muss daran denken, alles richtig zu machen. Fatal wäre dann z.B.</p>
<pre><code class="language-cpp">void foo() {
   buffer b; // auf dem Stack!
   start_operation(callback, b); // call by reference für b
} // b.~buffer() :(
</code></pre>
<p>Bessere Lösung wäre wohl</p>
<pre><code class="language-cpp">void callback(buffer*);

void foo() {
   auto bptr = make_unique&lt;buffer&gt;(); // wegen Exceptions etc.
   start_operation(callback, bptr.get());
   bptr.release(); // damit buffer gültig bleibt, kann aber leicht vergessen werden :(
}

void callback(buffer* b) {
   unique_ptr&lt;buffer&gt; bptr(b); // wieder Exception-safety + RAII
   ...
}
</code></pre>
<p>So mache ich es momentan, hier kann aber so viel vergessen werden. Aber das ist so viel manuelle Speicherverwaltung. Deswegen suche ich Alternativen.</p>
<p>2. Nutzer hat niemals Besitz am Puffer und die Library kümmert sich drum, also</p>
<pre><code class="language-cpp">void callback(buffer&amp; b) { ... } // nur Referenz, nachdem callback durch ist wird buffer gelöscht

void foo() {
   start_operation(callback, 50); // 50 Bytes Puffer
}
</code></pre>
<p>Vorteil: Viel weniger manuelle Verwaltung.<br />
Nachteil: Nutzer muss Puffer im Callback manuell kopieren, wenn er mit den Daten noch etwas anfangen will.</p>
<p>3. Besitz hin und her reichen:</p>
<pre><code class="language-cpp">void callback(buffer b) { ... }

void foo() {
   buffer b;
   start_operation(callback, std::move(b)); // irgendwann wird dann callback(std::move(b)) aufgerufen
}
</code></pre>
<p>Hat das irgendwelche Nachteile?<br />
Was würdet ihr machen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2450772</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2450772</guid><dc:creator><![CDATA[Pufferzone]]></dc:creator><pubDate>Sat, 18 Apr 2015 14:52:16 GMT</pubDate></item><item><title><![CDATA[Reply to Asynchrone Callbacks&#x2F;Buffer-Ownership on Sat, 18 Apr 2015 17:51:04 GMT]]></title><description><![CDATA[<p>Mein Vorschlag wäre:</p>
<pre><code>auto b = std::make_shared&lt;buffer&gt;();
start_operation([b](){
    // ...
});
</code></pre>
<p>Das wird so auch in den Asio Beispielen verwendet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2450793</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2450793</guid><dc:creator><![CDATA[patrick246]]></dc:creator><pubDate>Sat, 18 Apr 2015 17:51:04 GMT</pubDate></item></channel></rss>