<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 12 (filtered medium)"><base href="x-msg://4395/"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.apple-style-span
        {mso-style-name:apple-style-span;}
span.apple-tab-span
        {mso-style-name:apple-tab-span;}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div class=WordSection1><div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal style='margin-left:.5in'><span style='font-family:"Calibri","sans-serif";color:black'>The code example below is called from an external thread. Is that ok</span><o:p></o:p></p></div></div></div></blockquote><div><p class=MsoNormal style='margin-left:.5in'><o:p> </o:p></p></div><p class=MsoNormal style='margin-left:.5in'>No - absolutely not!!!   What you're trying to do - call "TaskScheduler::scheduleDelayedTask()" from an external thread - is extremely wrong! <o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>Look folks, how many times do I have to say this: A LIVE555 application runs as a single-thread of control (using an event loop, rather than threads, to provide concurrency).  If you want to communicate with a LIVE555 application from an external thread (i.e., from a thread other than the one that runs the LIVE555 event loop), then there are only two proper ways to do this:<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>1/ By setting a global variable, or<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>2/ Using an 'event trigger' - i.e., by calling "TaskScheduler::triggerEvent()".  Note that "triggerEvent()" is the ***only*** LIVE555 function that you may call from an external thread.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>This is all explained in the FAQ that you were all asked to read before posting to this mailing list!!!<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>In your case, you would do something like the following:<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>1/ Within the LIVE555 thread (e.g., somewhere after you've created "rtspClient"), call<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'><span class=apple-tab-span>            EventTriggerId</span> myStopStreamEvent = env.taskScheduler().createEventTrigger(StopStream);<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>2/ Later, from an external thread, you can call:<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'><span class=apple-tab-span>            env.taskScheduler().</span>triggerEvent(myStopStreamEvent, rtspClient);<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>and this will cause your "StopStream()" function to be called (with "rtspClient" as parameter) from the event loop - i.e., as a handled event.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:.5in'>(Note: For this to work, "env", "myStopStreamEvent" and "rtspClient" need to be global variables, so that they are visible to the external thread.  Note, though, that they are never *modified* by the external thread, only read by it.)<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'>Thanks a lot for taking the time to (again) clarify things.<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'>One last question on this, as I'm in the middle of reorganizing the code. <o:p></o:p></span></p><p class=MsoNormal><b><span style='font-family:"Calibri","sans-serif";color:#1F497D'>Shouldn't it be safe to create the rtspClient object in another thread?<o:p></o:p></span></b></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'>I can't really see a problem with that as it only appears to assign variables. Since I was so wrong before, I want to verify though ;-)<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'>Besides just being curious and want to find out, it would also simplify things in the application I'm working on. The application creates clients dynamically and starts up without any active clients. Having to create the rtspClient objects using triggers would introduce additional callbacks and making passing arguments a bit more complex.<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:"Calibri","sans-serif";color:#1F497D'>This is now the "main startup code":</span><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New";color:blue'>void</span><span style='font-size:11.0pt;font-family:"Courier New"'> InitStreamEngine()<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>{<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>     TaskScheduler* scheduler = BasicTaskScheduler::createNew();<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>     usageEnvironment = BasicUsageEnvironment::createNew(*scheduler);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>     myStartStreamEvent = usageEnvironment->taskScheduler().createEventTrigger((TaskFunc*)StartStreamEvent);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>     myStopStreamEvent = usageEnvironment->taskScheduler().createEventTrigger((TaskFunc*)StopStreamEvent);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>     mySeekAbsoluteEvent = usageEnvironment->taskScheduler().createEventTrigger((TaskFunc*)SeekAbsoluteEvent);<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:11.0pt;font-family:"Courier New"'>     usageEnvironment->taskScheduler().doEventLoop(&eventLoopWatchVariable);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Courier New"'>}<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Courier New"'>/Claes</span><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p></o:p></span></p></div></body></html>