<?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[[boost] sperren und freigeben von bereichen]]></title><description><![CDATA[<pre><code class="language-cpp">int main()
{
...
    vector&lt;Transmitter&gt; transmitter;
...
    for(int t00; t&lt;transmitter.size(); t++)
    {
       t.prepareForReceive()
       t.sendDataToOtherThread()
       t.receiveFromOtherThread();
    }
    ...
}
</code></pre>
<pre><code class="language-cpp">class MyTransmitter : public Transmitter {
public:
   void prepareForReceive() { /* lock(mutex)  */ }
   void sendDataToOtherThread() { ...}
   void weiseDatenZu() { /* unlock(mutex) */ }
   void receiveFromOtherThread() { /* mutex */ }
};
</code></pre>
<p>okay zum problem:<br />
verschiedene threads schicken sich daten über transmitter. transmitter ist eine abstrakte klasse und die methoden <em>prepareForReceive()</em>, <em>sendDataToOtherThread()</em> und <em>receiveFromOtherThread()</em> sind rein virtuell. in der hier aufgezeigten implementierung wird (ohne darauf im detail einzugehen) durch den aufruf von <em>sendDataToOtherThread()</em> in thread A im thread B letztich <em>weiseDatenZu()</em> aufgerufen. um sicherzugehen, dass dies erfolgt ist soll in <em>receiveFromOtherThread()</em> zur not so lange gewartet werden, bis die methode aufgerufen wurde.</p>
<p>erste überlegung war: waitcondiftion in i]prepareForReceive()[/i]. Problem: deadlock, da nun alle bei prepare warten und keiner was sendet. zweiter ansatz: waitcondition in <em>receiveFromOtherThread()</em> auf wait und notify_all in <em>weiseDatenZu</em>. gefahr: <em>weiseDatenZu()</em> wird VOR <em>receiveFromOtherThread()</em> (sind ja zwei threads...) -&gt; deadlock.<br />
dahe rwürd eich es gerne mit nem lock/mutex what ever machen. wie geht man da am besten vor, da es bei boost ja kein lock and unlock gibt. soll man da irgendwie den scope_lock verwednen? wenn ja wie? oder hat eine reine genrell bessere idee? ich kann nur innerhalb der klasse was ändern, da es diverse transmitter module gibt...<br />
bisher haben wir das problem so gelöst:</p>
<pre><code class="language-cpp">int main()
{
...
    vector&lt;Transmitter&gt; transmitter;
...
    for(int t00; t&lt;transmitter.size(); t++)
    {
       t.prepareForReceive() //&lt;-hatte keine funktion, methode war leer
       t.sendDataToOtherThread()
       #ifdef MyTransmitter
       syncThreads(); //&lt;- naja, hat die threads gesynced
       #endif
       t.receiveFromOtherThread();
    }
    ...
}
</code></pre>
<p>aber das ist gelinde gesagt zu fehleranfällig</p>
<p>Nun haben wir folgende Idee:</p>
<pre><code class="language-cpp">class MyTransmitter : public Transmitter {
public:
   void prepareForReceive() { scoped_lock(m); b=false; }
   void sendDataToOtherThread() { ...}
   void weiseDatenZu() { scoped_lock(m); b = true; c.notify_all() }
   void receiveFromOtherThread() { scoped_lock(m); if(!b) c.wait();  }
private:
   bool b;   
   boost::mutex m;
   boost::wait_condition c;

};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/174948/boost-sperren-und-freigeben-von-bereichen</link><generator>RSS for Node</generator><lastBuildDate>Sat, 19 Sep 2026 01:28:27 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/174948.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 05 Mar 2007 15:46:11 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Mon, 05 Mar 2007 16:21:26 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">int main()
{
...
    vector&lt;Transmitter&gt; transmitter;
...
    for(int t00; t&lt;transmitter.size(); t++)
    {
       t.prepareForReceive()
       t.sendDataToOtherThread()
       t.receiveFromOtherThread();
    }
    ...
}
</code></pre>
<pre><code class="language-cpp">class MyTransmitter : public Transmitter {
public:
   void prepareForReceive() { /* lock(mutex)  */ }
   void sendDataToOtherThread() { ...}
   void weiseDatenZu() { /* unlock(mutex) */ }
   void receiveFromOtherThread() { /* mutex */ }
};
</code></pre>
<p>okay zum problem:<br />
verschiedene threads schicken sich daten über transmitter. transmitter ist eine abstrakte klasse und die methoden <em>prepareForReceive()</em>, <em>sendDataToOtherThread()</em> und <em>receiveFromOtherThread()</em> sind rein virtuell. in der hier aufgezeigten implementierung wird (ohne darauf im detail einzugehen) durch den aufruf von <em>sendDataToOtherThread()</em> in thread A im thread B letztich <em>weiseDatenZu()</em> aufgerufen. um sicherzugehen, dass dies erfolgt ist soll in <em>receiveFromOtherThread()</em> zur not so lange gewartet werden, bis die methode aufgerufen wurde.</p>
<p>erste überlegung war: waitcondiftion in i]prepareForReceive()[/i]. Problem: deadlock, da nun alle bei prepare warten und keiner was sendet. zweiter ansatz: waitcondition in <em>receiveFromOtherThread()</em> auf wait und notify_all in <em>weiseDatenZu</em>. gefahr: <em>weiseDatenZu()</em> wird VOR <em>receiveFromOtherThread()</em> (sind ja zwei threads...) -&gt; deadlock.<br />
dahe rwürd eich es gerne mit nem lock/mutex what ever machen. wie geht man da am besten vor, da es bei boost ja kein lock and unlock gibt. soll man da irgendwie den scope_lock verwednen? wenn ja wie? oder hat eine reine genrell bessere idee? ich kann nur innerhalb der klasse was ändern, da es diverse transmitter module gibt...<br />
bisher haben wir das problem so gelöst:</p>
<pre><code class="language-cpp">int main()
{
...
    vector&lt;Transmitter&gt; transmitter;
...
    for(int t00; t&lt;transmitter.size(); t++)
    {
       t.prepareForReceive() //&lt;-hatte keine funktion, methode war leer
       t.sendDataToOtherThread()
       #ifdef MyTransmitter
       syncThreads(); //&lt;- naja, hat die threads gesynced
       #endif
       t.receiveFromOtherThread();
    }
    ...
}
</code></pre>
<p>aber das ist gelinde gesagt zu fehleranfällig</p>
<p>Nun haben wir folgende Idee:</p>
<pre><code class="language-cpp">class MyTransmitter : public Transmitter {
public:
   void prepareForReceive() { scoped_lock(m); b=false; }
   void sendDataToOtherThread() { ...}
   void weiseDatenZu() { scoped_lock(m); b = true; c.notify_all() }
   void receiveFromOtherThread() { scoped_lock(m); if(!b) c.wait();  }
private:
   bool b;   
   boost::mutex m;
   boost::wait_condition c;

};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1239656</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1239656</guid><dc:creator><![CDATA[muffmolch]]></dc:creator><pubDate>Mon, 05 Mar 2007 16:21:26 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Mon, 05 Mar 2007 20:17:25 GMT]]></title><description><![CDATA[<p>Grundsätzlich: wieso nicht, aber folgende Änderung:</p>
<pre><code class="language-cpp">void receiveFromOtherThread()
{
    scoped_lock(m);
//  if(!b) c.wait();
//    -&gt;
    while(!b) c.wait(); // while() wegen der Möglichkeit von &quot;spurious wakeups&quot;
}
</code></pre>
<p>Aber könntest du vielleicht erklären wie das &quot;Transmitter&quot; Inferface genau aussieht, und was das tut? Ich werde da nicht so ganz schlau draus...<br />
Also wann ruft der Client was auf, in welcher Reihenfolge muss er das tun um damit was zu erreichen, was für Garantien macht das Interface etc.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1239844</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1239844</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 05 Mar 2007 20:17:25 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Tue, 06 Mar 2007 07:21:05 GMT]]></title><description><![CDATA[<p>Zunächst: Polymorphie funktioniert nur über Zeiger und Referenzen. Damit kann dein vector&lt;Transmitter&gt; nicht einmal durch den Compiler gelangen (du willst Instanzen einer abstrakten Klasse anlegen) - du benötigst einen vector&lt;Transmitter*****&gt;.</p>
<p>Zweitens: Du hast hier nur einen einzigen Thread mit einer großen Schleife, die nacheinander über alle verfügbaren Transmitter läuft und für jeden prepareForRecieve(), sendDataToOtherThread() etc aufruft. Um wirklich parallel arbeiten zu können, mußt du die Nachrichtenschleife in eine zusätzliche Threadfunktion auslagern:</p>
<pre><code class="language-cpp">//Prinziplösung:
void ThreadFunc(void* trn)
{
  Transmitter* ptrans=(Transmitter*)trn;
  while(ptrans-&gt;active())
  {
    ptrans-&gt;prepareForReceive()
    ptrans-&gt;sendDataToOtherThread()
    ptrans-&gt;receiveFromOtherThread();
  }

...
vector&lt;Transmitter*&gt; transmitter;
...
for(int i=0;i&lt;transmitter.size();++i)
  StartThread(ThreadFunc,transmitter[i]);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1239995</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1239995</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Tue, 06 Mar 2007 07:21:05 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Tue, 06 Mar 2007 11:31:20 GMT]]></title><description><![CDATA[<p>naja, wie gesagt ich musste schon stark abstrahieren... und das mit der polymorphie versteht sich von selbst.<br />
eigentlich sind es keine threads sondern zwei executables, die mitinander über das RCF Framework komminizieren. Wir entwickeln einen parallelen Strömungslöser bei dem in der neuen Version zwei Prozesse die Strömungsdaten in der Berechnung via Transmitter übertragen:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
class ToTransmitter
{
public:
   ToTransmitter() {}
   virtual ~ToTransmitter() { cout&lt;&lt;&quot;tot\n&quot;&lt;&lt;endl; }

   virtual void sendData()=0;
   virtual void prepareForReceive() {}
   virtual T&amp;   receiveData()=0;
   virtual T&amp;   getData() { return this-&gt;data; }
protected:
   T data;
};
</code></pre>
<p>generell startet jeder prozess einen server, damit die prozesse über das RCF Framework kommunizieren koennen. Aber der Transmitter ist davon an sich unabhängig. Hier verwenden wir zusätzlich u.a. MPI. dann wird eben in prepareForReceive() eine request erzeugt und in receiveData wartet er bis dieser erfüllt wurde. es gibt auch &quot;LocalTransmitter&quot; die innerhalb eines Threads verwendet werden, nunja, die schreiben in und lesen aus demselben vector. Problem bei der implementierung der RCFTransmitter war, dass man nicht ohne #ifdef the prozesse syncen konnte. so kam es z.B. vor, dass Prozess A bereits die Daten in Prozess B überschrieben hat, obwohl B die alten noch benötigte... daher hatten wir zwischen send und receive einen sync eingebaut, was aber performance kostet, da an diesem punkt ALLE sein müssen bevor es weiter geht. da aber 250 clients austauschen und das netzwerk weniger belastet wird, wenn sie mit dem austausch anfangen sobald zwei prozesse soweit sind, wollten wir da ne andere lösung (u.v.a. dieses widerliche ifdef wegtreten).</p>
<p>nun haben wir folgende Lösung:</p>
<pre><code class="language-cpp">class ToRcfVectorReceiver : public ToTransmitter&lt; vector&lt; double &gt; &gt;
{
//static members
private:
   static map;
public:
   static void receiveDoubleVectorForTransmitter(int tag, const vector&lt; double &gt;&amp; data)
   {
      ...
      receiver = ToRcfVectorReceiver::map::getReceiver(tag);
      ...
      boost::mutex::scoped_lock fillBufferLock(receiver-&gt;fillBufferMutex);
      if(!receiver-&gt;fillBuffer) receiver-&gt;fillBufferWaitCond.wait(fillBufferLock);

      {
 	boost::mutex::scoped_lock fillBufferLock(receiver-&gt;fillBufferMutex);
        receiver-&gt;buffer       = data;   //zuweisung des buffers
        receiver-&gt;fillBuffer   = false;  //d.h. es liegen neue daten im buffer-&gt;nicht überschreiben
        receiver-&gt;bufferFilled = true;   //puffer voll, kann abgeholt werden
        receiver-&gt;bufferFilledWaitCond.notify_all();           
      }
   }

public:
   ToRcfVectorReceiver(const int&amp; tag) : ToTransmitter&lt; vector&lt; double &gt; &gt;()
   {
	...
      map::registerReceiver(tag);      
      fillBuffer   = true;
      bufferFilled = false;
   }

   ~ToRcfVectorReceiver()  {... }

    void sendData() { throw UbException(&quot;ToRcfVectorReceiver::sendData() - ToRcfVectorReceiver receives only&quot;); }

   vector&lt; double &gt;&amp; receiveData()
   {
      boost::mutex::scoped_lock bufferFilledLock(bufferFilledMutex);
      if(!bufferFilled) bufferFilledWaitCond.wait(bufferFilledLock);

      {
         boost::mutex::scoped_lock fillBufferLock(fillBufferMutex);
         this-&gt;getData().swap(buffer);  //übertag des buffers, nun kann dieser wieder überschrieben werden
         fillBuffer   = true;             
         bufferFilled = false;
         fillBufferWaitCond.notify_all();
         return this-&gt;getData();
      }
   }

private:
   int tag;

   bool             fillBuffer;
   boost::mutex     fillBufferMutex;
   boost::condition fillBufferWaitCond;

   bool             bufferFilled;
   boost::mutex     bufferFilledMutex;
   boost::condition bufferFilledWaitCond;

   vector&lt;double&gt; buffer;
};
</code></pre>
<p>hierbei wird sichergestellt, dass man den buffer erst wieder füllen kann, sobald der alter übernommen wurde. zudem wartet receive solange bis der puffer voll ist. wichtig hierbei: der SendTransmitter (hier nicht weiter dargestellt)ruft im remoteService eine methode auf, die letztlich die statische methode receiveDoubleVectorForTransmitter() aufruft...</p>
<p>also wenn da jemanden etwas geschickteres für den Receiver einfallen sollte, der darf das ruhig posten <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /><br />
wie gesagt sichergestellt werden muss:<br />
1. puffer darf erst empfangen werden, sobald dieser freigegeben wurde (andernfalls muss man warten)<br />
2. receiveData darf erst zurück kehren, wenn die daten empfangen wurden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1240161</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1240161</guid><dc:creator><![CDATA[muffmolch]]></dc:creator><pubDate>Tue, 06 Mar 2007 11:31:20 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Wed, 07 Mar 2007 01:15:08 GMT]]></title><description><![CDATA[<p>Hm. Klingt doch nach einer klassischen bounded FIFO queue ... nicht? Ist halt der Extremfall wo die &quot;Füllgrenze&quot; gleich 1 ist.</p>
<p>In dem Code sind IMHO auch &gt;= 2 Fehler drinnen:</p>
<ol>
<li>
<p>was ich schon geschrieben hatte: das &quot;if&quot; gehört durch ein &quot;while&quot; ersetzt</p>
</li>
<li>
<p>die 2. Mutex ist &quot;für die Fisch'&quot; (=unnötig). Hab jetzt nicht allzuviel darüber nachgedacht, aber der Code sieht auch überhaupt falsch aus mit den 2 Mutexen und den 2 bools. Einmal lockst du zuerst bufferFilledMutex und dann fillBufferMutex, dann wieder lockst du zuerst fillBufferMutex und dann (redundanterweise) nochmal fillBufferMutex. Und bufferFilled wird in receiveDoubleVectorForTransmitter geschrieben während bloss fillBufferMutex gelockt ist, wird aber in receiveData gelesen ohne dass fillBufferMutex gelockt wäre -&gt; böse. Auch die beiden &quot;bools&quot; sind IMHO unnötig (zumindest eines der beiden) -- machen ja beide das selbe, bloss mit inverser Logik. Und man kommt ganz ohne aus wenn man davon ausgehen kann dass nie leere Buffer verschickt werden (dann kann man nämlich einfach vector::empty statt dem bool nehmen), bzw. das Versenden eines leeren Buffers KEIN Empfangen eines leeren Buffers triggern soll, also ein NOP ist.</p>
</li>
<li>
<p>(kein Fehler, aber unschön): die doch sehr ähnlichen Namen (bufferFilled vs. fillBuffer) sind SEHR verwirrend. Und Verwirrung ist einer der Feinde von Korrektheit <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
</li>
</ol>
<p>Probier mal so:</p>
<pre><code class="language-cpp">class ToRcfVectorReceiver : public ToTransmitter&lt; vector&lt; double &gt; &gt;
{
	//static members
	typedef boost::mutex mutex_t;
	typedef boost::mutex::scoped_lock scoped_lock_t;
	typedef boost::condition condition_t;

private:
	static map;
public:
	static void receiveDoubleVectorForTransmitter(int tag, const vector&lt; double &gt;&amp; data)
	{
		...
		receiver = ToRcfVectorReceiver::map::getReceiver(tag);
		...
		scoped_lock_t lock(receiver-&gt;m_mutex);

		// wait until buffer is empty
		while (receiver-&gt;m_isBufferFull)
			receiver-&gt;m_bufferEmptiedCondition.wait(lock);

		// put data in buffer
		receiver-&gt;m_buffer = data;
		receiver-&gt;m_isBufferFull = true;

		// notify &quot;buffer filled&quot; waiters
		receiver-&gt;m_bufferFilledCondition.notify_all(); // notify_one müsste eigentlich reichen
	}

public:
	ToRcfVectorReceiver(const int&amp; tag) : ToTransmitter&lt; vector&lt; double &gt; &gt;()
	{
		...
		map::registerReceiver(tag);      
		m_isBufferFull = false;
	}

	~ToRcfVectorReceiver()  {... }

	void sendData() { throw UbException(&quot;ToRcfVectorReceiver::sendData() - ToRcfVectorReceiver receives only&quot;); }

	vector&lt; double &gt;&amp; receiveData()
	{
		scoped_lock_t lock(m_mutex);

		// wait until buffer is full
		while (!receiver-&gt;m_isBufferFull)
			receiver-&gt;m_bufferFilledCondition.wait(lock);

		// get data from buffer
		this-&gt;getData().swap(buffer);
		m_isBufferFull = false;

		// notify &quot;buffer emptied&quot; waiters
		m_bufferEmptiedCondition.notify_all(); // notify_one sollte auch hier reichen
		return this-&gt;getData();
	}

private:
	int tag;

	mutex_t m_mutex;
	boost::condition_t m_bufferFilledCondition;
	boost::condition_t m_bufferEmptiedCondition;

	std::vector&lt;double&gt; m_buffer;
	bool m_isBufferFull;
};
</code></pre>
<p>Die 2 verschiedenen Condition Variablen sind eine reine Optimierung, damit z.B. nicht reader von anderen readern aufgeweckt werden weil der Buffer gerade wieder leer gemacht wurde -- wäre ja sinnlos, die müssen dann ja sowieso weiter warten. Theoretisch ginge es aber genausogut mit nur einer Condition Variablen (bloss u.U. etwas langsamer), und dann kann man dann natürlich nichtmehr notify_one verwenden (i.e. die beiden Kommentare gelten dann nichtmehr) -- sollte auch klar sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1240684</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1240684</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 07 Mar 2007 01:15:08 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Wed, 07 Mar 2007 08:45:12 GMT]]></title><description><![CDATA[<p>klingt vernünftig <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /><br />
werde es gleich mal testen. gefällt mir sehr gut und die kritik ist berechtigt.<br />
(v.a. das mit dem mutex. das war tatsächlicj ein bug, der bereits behoben wurde, lag auch an der kritisierten namensgebung, die ich auch sehr irritierend fand)<br />
andere frage:</p>
<p>wieso soll man while anstatt if vor ner wait-condition verwenden?<br />
soll damit ausgeschlossen werden, dass bereits erneut geperrt wurde?<br />
das wäre zumindest eleganter, sollte aber hier per definiton nicht geschehen</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1240751</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1240751</guid><dc:creator><![CDATA[muffmolch]]></dc:creator><pubDate>Wed, 07 Mar 2007 08:45:12 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Wed, 07 Mar 2007 09:03:00 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/13960">@hustbaer</a><br />
1001. dank. da habe ich wohl etwas verquert gedacht...<br />
ärgert mich grad tierisch, aber deine lösung ist genu das was ich vor augen hatte und sie funktioniert einwandfrei!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1240761</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1240761</guid><dc:creator><![CDATA[muffmolch]]></dc:creator><pubDate>Wed, 07 Mar 2007 09:03:00 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Wed, 07 Mar 2007 23:01:21 GMT]]></title><description><![CDATA[<blockquote>
<p>wieso soll man while anstatt if vor ner wait-condition verwenden?<br />
soll damit ausgeschlossen werden, dass bereits erneut geperrt wurde?</p>
</blockquote>
<p>Kurze Antwort: weil man das so macht.</p>
<p>Lange Antwort: sehen wir uns mal die receiveDoubleVectorForTransmitter Funktion an:</p>
<p>Erst locken wir m_mutex.</p>
<p>Dann gucken wir ob der Puffer noch voll ist (m_isBufferFull), wenn ja legen wir uns schlafen, so lange bis m_bufferEmptiedCondition signalisiert wird. Dabei wird m_mutex temporär freigegeben (was auch so sein muss, weil sonst kein anderer Thread einen Lock auf m_mutex bekommen könnte, und auch niemand was am Zustand von m_isBufferFull ändern könnte, da der Zugriff auf m_isBufferFull ja über m_mutex synchronisiert wird).</p>
<p>Nun läuft irgendein anderer Thread durch receiveData, leert den Buffer, und signalisiert alle Waiter (singal_all!) die auf m_bufferEmptiedCondition warten. Angenommen es existiert noch ein 3. Thread, der genau an der selben Stelle wartet wie &quot;unser&quot; Thread (also auch in receiveDoubleVectorForTransmitter), dann gäbe es mit dem einfachen if() ein Problem: beide Threads wachen &quot;gleichzeitig&quot; auf; einer der beiden Threads kann m_mutex als erster sperren, macht den Buffer wieder voll, und gibt m_mutex wieder frei; danach bekommt der 2. Thread den Lock auf m_mutex, und ... der Buffer ist voll, der 2. Thread geht aber davon aus dass er leer wäre -&gt; *boom*. Mit dem while() passiert das nicht, da die Bedingung nochmal geprüft wird, der 2. Thread legt sich einfach wieder schlafen, bis das nächste mal m_bufferEmptiedCondition signalisiert wird.</p>
<p>---</p>
<p>Natürlich gibt es Fälle wo man beweisen kann dass solche &quot;spurious wakeups&quot; nicht vorkommen können, allerdings ist es IMHO viel einfacher wenn der Code überall &quot;while(!condition) condVar.wait(lock);&quot; verwendet -- der erneute Test kostet nicht gerade viel (auf die Laufzeit bezogen), und es ist einfacher zu beweisen dass der Code korrekt ist. Ganz davon abgesehen dass man sich dann weniger Gedanken bei eventuellen Änderungen machen muss.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1241335</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1241335</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 07 Mar 2007 23:01:21 GMT</pubDate></item><item><title><![CDATA[Reply to [boost] sperren und freigeben von bereichen on Thu, 08 Mar 2007 07:12:08 GMT]]></title><description><![CDATA[<p>verdammt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f621.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--pouting_face"
      title=":rage:"
      alt="😡"
    /> das klingt einleuchtend. werde diesbezüglich alle bedingungen ändern. danke, für den hinweis</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1241391</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1241391</guid><dc:creator><![CDATA[muffmolch]]></dc:creator><pubDate>Thu, 08 Mar 2007 07:12:08 GMT</pubDate></item></channel></rss>