<?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[ThreadPool - Boost.Thread]]></title><description><![CDATA[<p>Grüß' euch Kollegas,<br />
habe mal ne Frage. Und zwar habe ich einen ThreadPool geschrieben. Erste Problematiken traten auf, als ich den Pool selber implementiert habe. Bzw. gibt es keine copyconstructor. Das habe ich dann über einen Zeiger gelöst.</p>
<p>Hier erstmal der Code:</p>
<pre><code class="language-cpp">#ifndef TIMERPOOL_HEADER
#define TIMERPOOL_HEADER

#include &quot;StdIncludes.h&quot;

namespace Timer
{
	static void bla() { };

	class TimerPool : boost::noncopyable
	{
		private:
			std::vector&lt;std::pair&lt;boost::thread *,
				                  boost::posix_time::time_duration&gt;&gt; m_Pool;

			boost::scoped_ptr&lt;boost::thread&gt;                         m_pMainThread;   

			void TryToFindDuplications();

			template &lt;typename FunctionType&gt;
		    void LoopThread(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				            const boost::posix_time::time_duration &amp;TimeInterval);

		public:
			TimerPool() : i(0) { }

			template &lt;typename FunctionType&gt;
			void AddTimer(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				          const boost::posix_time::time_duration &amp;TimeInterval);

	};

	template &lt;typename FunctionType&gt;
	void TimerPool::AddTimer(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				             const boost::posix_time::time_duration &amp;TimeInterval)
	{
		boost::function0&lt;void&gt; Calling
		(
			boost::bind
			(
				&amp;Timer::TimerPool::LoopThread&lt;FunctionType&gt;,
				this,
				CallBackFnc,
				TimeInterval
			)
		);

		boost::thread TempThread(Calling);

		//TryToFindDuplications();

		m_Pool.push_back
		(
			std::make_pair&lt;boost::thread *, boost::posix_time::time_duration&gt;
			(
			   &amp;TempThread,
				TimeInterval
			)
		);

		TempThread.join();
	}

	template &lt;typename FunctionType&gt;
	void TimerPool::LoopThread(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
		                       const boost::posix_time::time_duration &amp;TimeInterval)
	{
		for(;;)
		{
			CallBackFnc();

			boost::this_thread::sleep(TimeInterval);
		}
	}

} // namespace Timer

#endif TIMERPOOL_HEADER
</code></pre>
<p>Funktioniert soweit auch alles, hier nun die Problemstellen:</p>
<pre><code class="language-cpp">#include &quot;KeyLogger.h&quot;

void TestFunc() { std::cout&lt;&lt;&quot;Hallo&quot;&lt;&lt;std::endl; }

void fnc() { std::cout&lt;&lt;&quot;no&quot;&lt;&lt;std::endl; }

KeyLogger::KeyLogger()
{
	m_pTimerPool.reset(new Timer::TimerPool());

	m_pTimerPool-&gt;AddTimer&lt;void&gt;(TestFunc, boost::posix_time::seconds(5));
	m_pTimerPool-&gt;AddTimer&lt;void&gt;(fnc, boost::posix_time::seconds(2));
}
</code></pre>
<p>Kurz erklärt: Die Funktion (1. Parameter) soll in einem Zeitintervall (2. Parameter) aufgerufen werden. Allerdings wird nur die Erste Funktion aufgerufen, bzw. alle 5 Sekunden &quot;Hallo&quot; ausgegeben. Das Programm verhält sich als würde der 2. AddTimer&lt;&gt;()-Aufruf gar nicht existieren -.-</p>
<p>Was ist da los?</p>
<p>Ich danke vielmals im Voraus! <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>
]]></description><link>https://www.c-plusplus.net/forum/topic/273177/threadpool-boost-thread</link><generator>RSS for Node</generator><lastBuildDate>Fri, 28 Aug 2026 07:45:57 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/273177.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 01 Sep 2010 17:11:55 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 17:11:55 GMT]]></title><description><![CDATA[<p>Grüß' euch Kollegas,<br />
habe mal ne Frage. Und zwar habe ich einen ThreadPool geschrieben. Erste Problematiken traten auf, als ich den Pool selber implementiert habe. Bzw. gibt es keine copyconstructor. Das habe ich dann über einen Zeiger gelöst.</p>
<p>Hier erstmal der Code:</p>
<pre><code class="language-cpp">#ifndef TIMERPOOL_HEADER
#define TIMERPOOL_HEADER

#include &quot;StdIncludes.h&quot;

namespace Timer
{
	static void bla() { };

	class TimerPool : boost::noncopyable
	{
		private:
			std::vector&lt;std::pair&lt;boost::thread *,
				                  boost::posix_time::time_duration&gt;&gt; m_Pool;

			boost::scoped_ptr&lt;boost::thread&gt;                         m_pMainThread;   

			void TryToFindDuplications();

			template &lt;typename FunctionType&gt;
		    void LoopThread(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				            const boost::posix_time::time_duration &amp;TimeInterval);

		public:
			TimerPool() : i(0) { }

			template &lt;typename FunctionType&gt;
			void AddTimer(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				          const boost::posix_time::time_duration &amp;TimeInterval);

	};

	template &lt;typename FunctionType&gt;
	void TimerPool::AddTimer(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				             const boost::posix_time::time_duration &amp;TimeInterval)
	{
		boost::function0&lt;void&gt; Calling
		(
			boost::bind
			(
				&amp;Timer::TimerPool::LoopThread&lt;FunctionType&gt;,
				this,
				CallBackFnc,
				TimeInterval
			)
		);

		boost::thread TempThread(Calling);

		//TryToFindDuplications();

		m_Pool.push_back
		(
			std::make_pair&lt;boost::thread *, boost::posix_time::time_duration&gt;
			(
			   &amp;TempThread,
				TimeInterval
			)
		);

		TempThread.join();
	}

	template &lt;typename FunctionType&gt;
	void TimerPool::LoopThread(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
		                       const boost::posix_time::time_duration &amp;TimeInterval)
	{
		for(;;)
		{
			CallBackFnc();

			boost::this_thread::sleep(TimeInterval);
		}
	}

} // namespace Timer

#endif TIMERPOOL_HEADER
</code></pre>
<p>Funktioniert soweit auch alles, hier nun die Problemstellen:</p>
<pre><code class="language-cpp">#include &quot;KeyLogger.h&quot;

void TestFunc() { std::cout&lt;&lt;&quot;Hallo&quot;&lt;&lt;std::endl; }

void fnc() { std::cout&lt;&lt;&quot;no&quot;&lt;&lt;std::endl; }

KeyLogger::KeyLogger()
{
	m_pTimerPool.reset(new Timer::TimerPool());

	m_pTimerPool-&gt;AddTimer&lt;void&gt;(TestFunc, boost::posix_time::seconds(5));
	m_pTimerPool-&gt;AddTimer&lt;void&gt;(fnc, boost::posix_time::seconds(2));
}
</code></pre>
<p>Kurz erklärt: Die Funktion (1. Parameter) soll in einem Zeitintervall (2. Parameter) aufgerufen werden. Allerdings wird nur die Erste Funktion aufgerufen, bzw. alle 5 Sekunden &quot;Hallo&quot; ausgegeben. Das Programm verhält sich als würde der 2. AddTimer&lt;&gt;()-Aufruf gar nicht existieren -.-</p>
<p>Was ist da los?</p>
<p>Ich danke vielmals im Voraus! <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>
]]></description><link>https://www.c-plusplus.net/forum/post/1947059</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947059</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Wed, 01 Sep 2010 17:11:55 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 18:36:36 GMT]]></title><description><![CDATA[<p>Ich kenn mich mit Boost 0 aus, aber ich glaube, dass der erste Call blockierend ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947086</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947086</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Wed, 01 Sep 2010 18:36:36 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 18:47:55 GMT]]></title><description><![CDATA[<p>Hey,<br />
danke erstmal für die Antwort! Du meinst den Aufruf von join() oder? Leider nein, der ist nicht blockierend, habe das ganze schon in einem Versuchs-Projekt ausprobiert und da geht's... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Danke!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947092</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947092</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Wed, 01 Sep 2010 18:47:55 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 18:56:23 GMT]]></title><description><![CDATA[<blockquote>
<p>Member function join()</p>
<p>Preconditions:<br />
this-&gt;get_id()!=boost::this_thread::get_id()</p>
<p>Effects:<br />
If *this refers to a thread of execution, waits for that thread of execution to complete.</p>
</blockquote>
<p>Aber das könnte man eigentlich auch mit einem Debugger rausfinden, oder ?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947098</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947098</guid><dc:creator><![CDATA[nurf]]></dc:creator><pubDate>Wed, 01 Sep 2010 18:56:23 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 19:03:31 GMT]]></title><description><![CDATA[<p>Aber das geht auch:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;boost/thread.hpp&gt;

static void fnc1() { for(;;) { std::cout&lt;&lt;&quot;hi&quot;&lt;&lt;std::endl; } }
static void fnc2() { for(;;) { std::cout&lt;&lt;&quot;tschau&quot;&lt;&lt;std::endl; } }

int main()
{
	boost::thread thread1(fnc1);
	boost::thread thread2(fnc2);

	thread1.join();
	thread2.join();
}
</code></pre>
<p>Wie sollte ich es sonst machen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947103</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947103</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Wed, 01 Sep 2010 19:03:31 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 19:14:39 GMT]]></title><description><![CDATA[<p>Die Methode join blockiert immer, bis die Ausführung des zugehörigen Threads beendet ist.<br />
Dies geschieht aber nie, weil er in einer Endlosschleife gefangen ist.</p>
<p>Ich vermute, dass der Thread in deinem Testprojekt sofort terminiert, und der Aufruf von join damit nicht mehr blockiert.</p>
<p>Ich würde das boost::thread - Objekt einfach über boost::shared_ptr (oder Ähnliches) verwalten und das join weglassen.</p>
<p>Nur im Destruktor des Pools musst du dann aufpassen, dass du auf allen Threads join aufrufst, bevor die Objekte zerstört werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947107</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947107</guid><dc:creator><![CDATA[quasar]]></dc:creator><pubDate>Wed, 01 Sep 2010 19:14:39 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 19:23:39 GMT]]></title><description><![CDATA[<p>Kóyaánasqatsi schrieb:</p>
<blockquote>
<p>Aber das geht auch:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;boost/thread.hpp&gt;

static void fnc1() { for(;;) { std::cout&lt;&lt;&quot;hi&quot;&lt;&lt;std::endl; } }
static void fnc2() { for(;;) { std::cout&lt;&lt;&quot;tschau&quot;&lt;&lt;std::endl; } }

int main()
{
	boost::thread thread1(fnc1);
	boost::thread thread2(fnc2);

	thread1.join();
	thread2.join();
}
</code></pre>
<p>Wie sollte ich es sonst machen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
</blockquote>
<p>Aber entspricht folgendes nicht etwa deinem Timer-Code ?</p>
<pre><code class="language-cpp">boost::thread thread1(fnc1);
	thread1.join();

	boost::thread thread2(fnc2);
	thread2.join();
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1947112</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947112</guid><dc:creator><![CDATA[nurf]]></dc:creator><pubDate>Wed, 01 Sep 2010 19:23:39 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 19:50:19 GMT]]></title><description><![CDATA[<p>Ok.<br />
Mit dem Code terminiert der Thread auch nicht. Hier liegt es tatsächlich an der unterschiedlichen Reihenfolge der Aufrufe, dass beide Threads gestartet werden.</p>
<p>Endlosschleifen würde ich generell nicht verwenden, um den Thread am Laufen zu halten.<br />
Was spricht gegen eine Abbruchbedingung, mit der man den Thread auch vernünftig terminieren kann?<br />
Im einfachsten Fall kann man dem Thread ja über eine Membervariable signalisieren, dass er anhalten soll.<br />
Andernfalls wirst du bei jedem Aufruf von join das Problem haben, dass der aufrufende Thread ewig wartet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947125</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947125</guid><dc:creator><![CDATA[quasar]]></dc:creator><pubDate>Wed, 01 Sep 2010 19:50:19 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 19:56:09 GMT]]></title><description><![CDATA[<p>Hab's jetzt so gemacht wie du sagtest:</p>
<pre><code class="language-cpp">#ifndef TIMERPOOL_HEADER
#define TIMERPOOL_HEADER

#include &quot;StdIncludes.h&quot;

namespace Timer
{
	static void bla() { };

	class TimerPool : boost::noncopyable
	{
		private:
			std::vector&lt;std::pair&lt;boost::shared_ptr&lt;boost::thread&gt;,
				                  boost::posix_time::time_duration&gt;&gt; m_Pool;

			boost::scoped_ptr&lt;boost::thread&gt;                         m_pMainThread;   

			void TryToFindDuplications();

			template &lt;typename FunctionType&gt;
		    void LoopThread(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				            const boost::posix_time::time_duration &amp;TimeInterval);

		public:
			TimerPool() { }

			template &lt;typename FunctionType&gt;
			void AddTimer(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				          const boost::posix_time::time_duration &amp;TimeInterval);

	};

	template &lt;typename FunctionType&gt;
	void TimerPool::AddTimer(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
				             const boost::posix_time::time_duration &amp;TimeInterval)
	{
		boost::function0&lt;void&gt; Calling
		(
			boost::bind
			(
				&amp;Timer::TimerPool::LoopThread&lt;FunctionType&gt;,
				this,
				CallBackFnc,
				TimeInterval
			)
		);

		boost::shared_ptr&lt;boost::thread&gt; TempThread(new boost::thread(Calling));
		//TryToFindDuplications();

		m_Pool.push_back
		(
			std::make_pair&lt;boost::shared_ptr&lt;boost::thread&gt;, boost::posix_time::time_duration&gt;
			(
			    TempThread,
				TimeInterval
			)
		);
	}

	template &lt;typename FunctionType&gt;
	void TimerPool::LoopThread(boost::function&lt;FunctionType (void)&gt; CallBackFnc,
		                       const boost::posix_time::time_duration &amp;TimeInterval)
	{
		for(;;)
		{
			CallBackFnc();

			boost::this_thread::sleep(TimeInterval);
		}
	}

} // namespace Timer

#endif TIMERPOOL_HEADER
</code></pre>
<p>Jedoch wird &quot;Hallo&quot; nur einmal ausgegeben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947128</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947128</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Wed, 01 Sep 2010 19:56:09 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 20:14:51 GMT]]></title><description><![CDATA[<p>Das ist auch korrekt. Dein Programm blockiert nun nicht mehr und terminiert inklusive aller Threads nach Verlassen der main - Funktion.<br />
Diese Zeit reichte in diesem Fall nur für eine Ausgabe.<br />
Um das zu verhindern, müsstest du irgendwo warten. Allerdings erst nach allen AddTimer - Aufrufen.<br />
Aber ohne den Zweck deines Programms zu kennen, kann ich dir keine genauen Tipps geben, wo du warten solltest.</p>
<p>Soll der Benutzer das Programm irgendwann beenden oder soll es terminieren, nachdem es eine bestimmte Aufgabe erledigt hat?<br />
Das wären die beiden Fälle, die mir spontan einfallen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947129</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947129</guid><dc:creator><![CDATA[quasar]]></dc:creator><pubDate>Wed, 01 Sep 2010 20:14:51 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 20:24:57 GMT]]></title><description><![CDATA[<p>Verstehe ich nicht ganz, das ist doch eine Endlosschleife? Die Schleife soll eiegtnlich so lange geloopt werden bis sich Wert x ändert. Dazu gibt es dann später eine Fuktion wie StopTimer(Signatur x);.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947131</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947131</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Wed, 01 Sep 2010 20:24:57 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Wed, 01 Sep 2010 21:25:45 GMT]]></title><description><![CDATA[<p>StopTimer ist schon mal eine gute Idee. So wird auch auch die Endlosschleife eliminiert.</p>
<p>Jetzt aber zum eigentlichen Problem.<br />
Sobald du einen neuen Thread erstellt hast, läuft der Rest des Programms ja einfach weiter (es sei denn, man blockiert die Ausführung).</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;boost/thread.hpp&gt;

void Callback()
{
	while(true)
		std::cout &lt;&lt; &quot;Hello world!&quot; &lt;&lt; std::endl;
}

int main()
{
	//Starten eines neuen Threads -&gt; Aufspalten der Codeausführung
	//z.B. in AddTimer
	boost::thread thread(Callback);

	//der alte main-Thread läuft weiter
	//der neue Thread führt die Endlosschleife aus

	//vor dem Ende des Programms, sollte man warten, bis alle Threads terminiert sind.
	//z.B. mit thread.join();
	//thread.join();

	//Der main-Thread verlässt hier die main-Funktion und das Programm
	//terminiert, inklusive aller noch laufenden Threads
	std::cout &lt;&lt; &quot;Programm terminiert&quot; &lt;&lt; std::endl;
	return 0;
}
</code></pre>
<p>Ich hoffe, durch das Beispiel wird alles ein bisschen klarer.<br />
Einfach mal den Code austesten.<br />
Ich habe den Code vorher nicht getestet, sollte aber kompilieren.</p>
<p>Dein Programm terminiert also und hat gar keine Zeit viel auszugeben.<br />
Es wartet nicht automatisch darauf, dass alle Threads terminieren.<br />
Das ist gerade die Aufgabe von join.</p>
<p>Also musst du nach den AddTimer - Aufrufen auf irgendetwas warten, z.B. auf eine Variablenänderung. Dann terminiert das Programm auch nicht vorzeitig.</p>
<p>Es wäre aber im Folgenden hilfreich, wenn du mal ein Beispiel zur späteren Nutzung der StopTimer - Methode zeigen könntest.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947147</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947147</guid><dc:creator><![CDATA[quasar]]></dc:creator><pubDate>Wed, 01 Sep 2010 21:25:45 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Thu, 02 Sep 2010 10:53:49 GMT]]></title><description><![CDATA[<p>Du hampelst doch ständig mit <code>boost::asio</code> herum. Wieso benutzt Du nicht einfach <code>boost::asio::deadline_timer</code> ? Der macht quasi genau das, was Du da von Hand nachbaust.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947280</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947280</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 02 Sep 2010 10:53:49 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Thu, 02 Sep 2010 12:31:38 GMT]]></title><description><![CDATA[<p>@last post<br />
Nein, ich möchte das gerne so progg0rn. Aber trotzdem danke, werde ich mir auch noch angucken.</p>
<p>@quasar<br />
Du sagtest ja es sollte funktionieren, wenn der Thread solange wartet und erst dann stoppt, wenn eine Variablenänderung erfolgt.</p>
<p>Dann sollte das ja funktionieren:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;boost/thread.hpp&gt;

static unsigned int a = 1;

void Callback()
{
    while(a &lt;= 1000)
	{
        std::cout &lt;&lt; a++ &lt;&lt; std::endl;
	}
}

int main()
{
    //Starten eines neuen Threads -&gt; Aufspalten der Codeausführung
    //z.B. in AddTimer
    boost::thread thread(Callback);

    //der alte main-Thread läuft weiter
    //der neue Thread führt die Endlosschleife aus

    //vor dem Ende des Programms, sollte man warten, bis alle Threads terminiert sind.
    //z.B. mit thread.join();
    //thread.join();

    //Der main-Thread verlässt hier die main-Funktion und das Programm
    //terminiert, inklusive aller noch laufenden Threads
    std::cout &lt;&lt; &quot;Programm terminiert&quot; &lt;&lt; std::endl;
    return 0;
}
</code></pre>
<p>Tut's aber nicht. Gibt gar nichts aus <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":/"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947323</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947323</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Thu, 02 Sep 2010 12:31:38 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Thu, 02 Sep 2010 12:36:58 GMT]]></title><description><![CDATA[<p>Kóyaánasqatsi schrieb:</p>
<blockquote>
<pre><code class="language-cpp">//Der main-Thread verlässt hier die main-Funktion und das Programm
    //terminiert, inklusive aller noch laufenden Threads
    std::cout &lt;&lt; &quot;Programm terminiert&quot; &lt;&lt; std::endl;
    return 0;
</code></pre>
</blockquote>
<p>Ohne ein <code>thread::join</code> geht das so nicht. Das hat quasar auch eigentlich recht deutlich gemacht. <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="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1947327</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947327</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 02 Sep 2010 12:36:58 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Thu, 02 Sep 2010 13:07:46 GMT]]></title><description><![CDATA[<p>Mir ist gerade langweilig, daher mal ein kleines Beispiel (ungetestet):</p>
<pre><code class="language-cpp">class SuspekteFadenKlasse
{
public:
    SuspekteFadenKlasse(std::size_t fadenZahl);

    void stoppeLaufmaschen();

private:

    void laufmasche(std::size_t id);

    boost::ptr_vector&lt;boost::thread&gt; fadenBecken;
    bool maschenLaufen;
};

SuspekteFadenKlasse::SuspekteFadenKlasse(std::size_t fadenZahl)
: maschenLaufen(true)
{
    for(std::size_t n = 0; n != fadenZahl; ++n)
    {
        fadenBecken.push_back(new boost::thread(boost::bind(&amp;SuspekteFadenKlasse::laufmasche, this, n)));
    }
}

void SuspekteFadenKlasse::stoppeLaufmaschen()
{
    maschenLaufen = false;
    for(std::size_t n = 0; n != fadenBecken.size(); ++n)
    {
        fadenBecken[n].join(); //alle Threads durchlaufen und aufs Ende warten
    }
}

void SuspekteFadenKlasse::laufmasche(std::size_t id)
{
    std::ostringstream amazonasDelta;
    while(maschenLaufen)
    {
        //stringstream sorgt auf den handelsueblichen compilern (MSVC, gcc)
        //dafuer, dass die Ausgabe nicht durcheinander geht
        amazonasDelta.str(&quot;&quot;);
        amazonasDelta &lt;&lt; &quot;Ich bin aus Faden: &quot; &lt;&lt; id &lt;&lt; '\n';
        std::cout &lt;&lt; amazonasDelta.str();
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
}

int main()
{
    SuspekteFadenKlasse strumpfhose(5);
    //wuerde jetzt erstmal auch einfach so beenden...
    std::string kommando;
    while(kommando != &quot;quit&quot;)
    {
        std::getline(std::cin, kommando); //...aber wir warten.
    }
    strumpfhose.stoppeLaufmaschen(); //hier wird darauf gewartet, dass alle threads terminieren
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1947336</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1947336</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 02 Sep 2010 13:07:46 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Fri, 03 Sep 2010 23:13:58 GMT]]></title><description><![CDATA[<p>Ich will ein Kind von dir. Mal wieder.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1948017</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948017</guid><dc:creator><![CDATA[Kóyaánasqatsi]]></dc:creator><pubDate>Fri, 03 Sep 2010 23:13:58 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Sat, 04 Sep 2010 00:31:31 GMT]]></title><description><![CDATA[<p>Also da sind streng genommen zwei Fehler drin.</p>
<ol>
<li>
<p>Man darf nicht einfach so mit mehreren Threads gleichzeitig nach std::cout schreiben. Die meisten Compiler crashen nicht, aber garantiert ist nix. k.A. ob der kommende Standard das ändern wird.</p>
</li>
<li>
<p>Das &quot;cancel flag&quot; ist nicht &quot;synchronisiert&quot;. Die Minimallösung wäre es <code>volatile</code> zu machen. Die bessere Lösung wäre es mit einer Mutex zu schützen.</p>
</li>
</ol>
<p>Was die komischen Namen sollen entzieht sich mir im Moment, aber ich mache mal einfach mit <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>
<pre><code class="language-cpp">#include &lt;boost/thread.hpp&gt;
#include &lt;boost/ptr_container/ptr_vector.hpp&gt;
#include &lt;boost/bind.hpp&gt;

class SuspekteFadenKlasse 
{ 
public: 
	SuspekteFadenKlasse(std::size_t fadenZahl); 

	void stoppeLaufmaschen(); 

private: 
	void laufmasche(std::size_t id); 

	boost::ptr_vector&lt;boost::thread&gt; fadenBecken;  // müsste mit aktuellen compilern auch mit nem normalen std::vector gehen, move semantik und so

	boost::mutex torWaechter;
	boost::condition_variable_any postillion;
	bool maschenLaufen; 
}; 

SuspekteFadenKlasse::SuspekteFadenKlasse(std::size_t fadenZahl) 
: maschenLaufen(true) 
{ 
	for(std::size_t n = 0; n != fadenZahl; ++n) 
	{ 
		fadenBecken.push_back(new boost::thread(boost::bind(&amp;SuspekteFadenKlasse::laufmasche, this, n))); 
	} 
} 

void SuspekteFadenKlasse::stoppeLaufmaschen() 
{ 
	{
		boost::unique_lock&lt;boost::mutex&gt; torSchluss(torWaechter);
		maschenLaufen = false; 
		postillion.notify_all();
	}

	for(std::size_t n = 0; n != fadenBecken.size(); ++n) 
	{ 
		fadenBecken[n].join(); //alle Threads durchlaufen und aufs Ende warten 
	} 
} 

void SuspekteFadenKlasse::laufmasche(std::size_t id) 
{ 
	boost::unique_lock&lt;boost::mutex&gt; torSchluss(torWaechter);
	while(maschenLaufen)
	{ 
		std::cout &lt;&lt; &quot;Ich bin aus Faden: &quot; &lt;&lt; id &lt;&lt; '\n'; 

		// wenns was zu machen gibt was länger dauert, sollte man während man es macht dem torWaechter frei geben.
		// allerdings sollte der torWaechter NICHT frei haben, während man maschenLaufen abfragt.

		// warten bis es post gibt, allerdings maximal 1 sekunde
		postillion.timed_wait(torWaechter, boost::posix_time::seconds(1));
	} 
} 

int main() 
{ 
	SuspekteFadenKlasse strumpfhose(5); 
	//wuerde jetzt erstmal auch einfach so beenden... 
	std::string kommando; 
	while(kommando != &quot;quit&quot;) 
	{ 
		std::getline(std::cin, kommando); //...aber wir warten. 
	} 
	strumpfhose.stoppeLaufmaschen(); //hier wird darauf gewartet, dass alle threads terminieren 
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1948023</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948023</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 04 Sep 2010 00:31:31 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Sat, 04 Sep 2010 09:58:38 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Also da sind streng genommen zwei Fehler drin.</p>
<ol start="2">
<li>Das &quot;cancel flag&quot; ist nicht &quot;synchronisiert&quot;. Die Minimallösung wäre es <code>volatile</code> zu machen. Die bessere Lösung wäre es mit einer Mutex zu schützen.</li>
</ol>
</blockquote>
<p>Leider sind in Punkt 2) auch zwei Fehler drin.</p>
<p>1. Volatile ist kein atomic_compare_and_set, womit also Race Conditions genauso wenig ausgeschlossen sind.</p>
<p>2. Ein Mutex ist keine Memory-Fence. Da ein x86 mit out-of-order execution arbeitet, ist ein Write-Back vor dem Mutex-Unlock von dem Flag nicht garantiert.<br />
Warum es aber meistens funktioniert ist:<br />
2.1 Weil die meisten Mutex-Implementierungen eine Memory-Fence verwenden.<br />
2.2 Weil x86er Cache-Kohärent sind.</p>
<p>Wenn ich jedes mal einen Euro kriegen würde, wenn jemand volatile in Zusammenhang mit Threads erwähnt ...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1948064</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948064</guid><dc:creator><![CDATA[nurf]]></dc:creator><pubDate>Sat, 04 Sep 2010 09:58:38 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Sat, 04 Sep 2010 15:09:13 GMT]]></title><description><![CDATA[<p>nurf schrieb:</p>
<blockquote>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Also da sind streng genommen zwei Fehler drin.</p>
<ol start="2">
<li>Das &quot;cancel flag&quot; ist nicht &quot;synchronisiert&quot;. Die Minimallösung wäre es <code>volatile</code> zu machen. Die bessere Lösung wäre es mit einer Mutex zu schützen.</li>
</ol>
</blockquote>
<p>Leider sind in Punkt 2) auch zwei Fehler drin.</p>
<p>1. Volatile ist kein atomic_compare_and_set, womit also Race Conditions genauso wenig ausgeschlossen sind.</p>
</blockquote>
<p>volatile ist für ein Cancel-Flag praktisch gesehen ausreichend. Für ein Cancel-Flag brauche ich weder atomare Zugriffe noch Memory-Ordering. Wichtig ist nur dass die Änderung des schreibenden Threads irgendwann mal für andere Threads sichtbar wird, und dass der lesende Thread nie &quot;true&quot; liest, obwohl keiner jemals &quot;true&quot; reingeschrieben hat. Ganz streng genommen garantiert das der C++ Standard nicht, aber ich kenne keine Archtektur wo es nicht funktionieren würde. Auch Alpha etc. sind diesbezüglich problemlos.<br />
Wenn es um mehr als nur ein Cancel-Flag geht, braucht man natürlich andere Mittel.</p>
<blockquote>
<p>2. Ein Mutex ist keine Memory-Fence. Da ein x86 mit out-of-order execution arbeitet, ist ein Write-Back vor dem Mutex-Unlock von dem Flag nicht garantiert.<br />
Warum es aber meistens funktioniert ist:<br />
2.1 Weil die meisten Mutex-Implementierungen eine Memory-Fence verwenden.<br />
2.2 Weil x86er Cache-Kohärent sind.</p>
</blockquote>
<p>Was eine Mutex genau ist, ist wohl Definitionssache. Ich verwende hier boost::mutex, und boost::mutex garantiert acquire/release Semantik. Egal auf welcher Plattform. PTHREADs garantiert soweit ich weiss das selbe, Windows CRITICAL_SECTIONs und Mutexen ebenso.<br />
Ich sehe hier also nicht mal ganz ganz streng genommen einen Fehler.</p>
<blockquote>
<p>Wenn ich jedes mal einen Euro kriegen würde, wenn jemand volatile in Zusammenhang mit Threads erwähnt ...</p>
</blockquote>
<p>Wenn ich jedes mal einen Euro kriegen würde, wenn jemand eine sinnlose Bemerkung macht...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1948117</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948117</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 04 Sep 2010 15:09:13 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Sat, 04 Sep 2010 16:45:34 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>volatile ist für ein Cancel-Flag praktisch gesehen ausreichend. Für ein Cancel-Flag brauche ich weder atomare Zugriffe noch Memory-Ordering. Wichtig ist nur dass die Änderung des schreibenden Threads irgendwann mal für andere Threads sichtbar wird, und dass der lesende Thread nie &quot;true&quot; liest, obwohl keiner jemals &quot;true&quot; reingeschrieben hat.</p>
</blockquote>
<p>Dann lass das volatile in Zukunft weg und du wirst sehen, es funktioniert trotzdem.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1948152</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948152</guid><dc:creator><![CDATA[nurf]]></dc:creator><pubDate>Sat, 04 Sep 2010 16:45:34 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Sun, 05 Sep 2010 14:42:18 GMT]]></title><description><![CDATA[<p>nurf schrieb:</p>
<blockquote>
<p>hustbaer schrieb:</p>
<blockquote>
<p>volatile ist für ein Cancel-Flag praktisch gesehen ausreichend. Für ein Cancel-Flag brauche ich weder atomare Zugriffe noch Memory-Ordering. Wichtig ist nur dass die Änderung des schreibenden Threads irgendwann mal für andere Threads sichtbar wird, und dass der lesende Thread nie &quot;true&quot; liest, obwohl keiner jemals &quot;true&quot; reingeschrieben hat.</p>
</blockquote>
<p>Dann lass das volatile in Zukunft weg und du wirst sehen, es funktioniert trotzdem.</p>
</blockquote>
<p>Das tut es nur, wenn der Code in der Schleife für den Compiler zu kompliziert wird, so dass er nichtmehr sicher sein kann, dass das Cancel-Flag nicht irgendwo geändert werden könnnte.</p>
<p>Das funktioniert z.B. nicht:</p>
<pre><code class="language-cpp">while (!cancelFlag);
</code></pre>
<p>Hier erkennt der Compiler dass cancelFlag in der Schleife nicht verändert wird, und zieht den Test &quot;!cancelFlag&quot; aus der Schleife raus.<br />
volatile verhindert das.</p>
<p>Wieso ich damit pokern sollte dass der Compiler die mögliche (und durch das fehlende volatile erlaubte) Optimierung nicht findet, weiss ich nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1948467</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948467</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sun, 05 Sep 2010 14:42:18 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Sun, 05 Sep 2010 16:57:38 GMT]]></title><description><![CDATA[<p>Also entweder verwechselst du da was mit Java oder C#.</p>
<p><a href="http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/" rel="nofollow">http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/</a></p>
<p>Soll mir egal sein, im Internet findet sich genug zu der Thematik.</p>
<p>Noch ein Zitat zum Abschluss:</p>
<blockquote>
<p>If your multithreaded code works properly with volatile and doesn’t work without, then either your C++ implementation carefully implemented volatile to work with threads (less likely), or you simply got lucky (more likely).</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/1948529</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948529</guid><dc:creator><![CDATA[nurf]]></dc:creator><pubDate>Sun, 05 Sep 2010 16:57:38 GMT</pubDate></item><item><title><![CDATA[Reply to ThreadPool - Boost.Thread on Mon, 06 Sep 2010 00:31:17 GMT]]></title><description><![CDATA[<p>Ich verwechsle nichts, und ich kenne auch die diversen Zitate, Artikel etc.</p>
<p>Volatile in C bzw. C++ zwingt den Compiler dazu, eine load bzw. store Instruction zu erzeugen. Nicht mehr und nicht weniger.</p>
<p>Um den Rest kümmert sich in diesem Fall die CPU, da, wie ich schon geschrieben habe, Speicher-Sichtbarkeit etc. für ein Cancel-Flag vollkommen wurscht sind. Genauso ob der Zugriff atomar erfolgt oder nicht.</p>
<p>Das ist einer der wenigen Spezialfälle, wo man in C bzw. C++ mit volatile, ohne zusätzliche, &quot;freiwillige&quot; Garantien des Compilers, etwas Sinnvolles anstellen kann.</p>
<p>Vorausgesetzt man hat eine CPU, die die Caches *irgendwann mal* selbst updated, ODER ein Betriebssystem welches hin und wieder mal etwas macht was die Caches flusht. Und ich schätze dass das jedes OS welches Threads verwendet tut, nämlich wenn der Scheduler anläuft um zu gucken ob auf einen anderen Thread umgeschaltet werden sollte.</p>
<p>Ich weiss dass es keine vom Standard garantierte Sache ist. Ich sage nur: es funktioniert so-gut-wie überall, wenn nicht überhaupt überall.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1948642</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1948642</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 06 Sep 2010 00:31:17 GMT</pubDate></item></channel></rss>