FifoBase.cc
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:10k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const FifoBase_cc_Version =
  51.     "$Id: FifoBase.cc,v 1.18 2001/04/13 18:53:03 icahoon Exp $";
  52. #include "Lock.hxx"
  53. #include "TimeVal.hxx"
  54. using Vocal::FifoBase;
  55. using Vocal::Threads::Lock;
  56. using Vocal::TimeAndDate::TimeVal;
  57. template <class Msg>
  58. FifoBase<Msg>::FifoBase()
  59.     : myShutdown(false)
  60. {
  61. }
  62. template <class Msg>
  63. FifoBase<Msg>::~FifoBase()
  64. {
  65. }
  66. template <class Msg>
  67. void
  68. FifoBase<Msg>::add(const Msg & msg)
  69. {
  70.     Lock lock(myMutex); (void)lock;
  71.     if ( myShutdown )
  72.     {
  73.         return;
  74.     }
  75.     myFifo.push_back(new Msg(msg));
  76.     try
  77.     {
  78.         wakeup();
  79.     }
  80.     catch ( VException & )
  81.     {
  82.         assert(0);
  83.     }
  84. }
  85. template <class Msg>
  86. FifoBase<Msg>::EventId
  87. FifoBase<Msg>::addDelay(
  88.     const Msg     &   msg,
  89.     const TimeVal   &   relativeTimeout
  90. )
  91. {
  92.     Lock lock(myMutex); (void)lock;
  93.     if ( myShutdown )
  94.     {
  95.         return ( 0 );
  96.     }
  97.     EventId newId = myTimer.add(new Msg(msg), relativeTimeout);
  98.     postAddTimed(newId);
  99.     return ( newId );
  100. }
  101. template <class Msg>
  102. FifoBase<Msg>::EventId
  103. FifoBase<Msg>::addUntil(
  104.     const Msg     &   msg,
  105.     const TimeVal   &   when
  106. )
  107. {
  108.     Lock lock(myMutex); (void)lock;
  109.     if ( myShutdown )
  110.     {
  111.         return ( 0 );
  112.     }
  113.     TimerEntryId newId = myTimer.add(new Msg(msg), when, false);
  114.     postAddTimed(newId);
  115.     return ( newId );
  116. }
  117. template <class Msg>
  118. FifoBase<Msg>::EventId
  119. FifoBase<Msg>::addDelayMs(
  120.     const Msg             &   msg,
  121.     const milliseconds_t        pRelativeTimeout
  122. )
  123. {
  124.     Lock lock(myMutex); (void)lock;
  125.     if ( myShutdown )
  126.     {
  127.         return ( 0 );
  128.     }
  129.     milliseconds_t relativeTimeout = pRelativeTimeout;
  130.     if ( relativeTimeout < 0 )
  131.     {
  132.         relativeTimeout = 0;
  133.     }
  134.     TimerEntryId newId = myTimer.add(new Msg(msg), relativeTimeout);
  135.     postAddTimed(newId);
  136.     return ( newId );
  137. }
  138. template <class Msg>
  139. FifoBase<Msg> ::EventId
  140. FifoBase<Msg> ::addUntilMs(
  141.     const Msg             &   msg,
  142.     const milliseconds_t        when
  143. )
  144. {
  145.     Lock lock(myMutex); (void)lock;
  146.     if ( myShutdown )
  147.     {
  148.         return ( 0 );
  149.     }
  150.     EventId newId = myTimer.add(new Msg(msg), when, false);
  151.     postAddTimed(newId);
  152.     return ( newId );
  153. }
  154. template <class Msg>
  155. void
  156. FifoBase<Msg>::cancel(EventId id)
  157. {
  158.     if ( id == 0 )
  159.     {
  160.         return ;
  161.     }
  162.     Lock lock(myMutex); (void)lock;
  163.     if ( !myTimer.cancel(id) )
  164.     {
  165.         // If the timer didn't hold the message to cancel, walk through
  166.         // the queue and see if we have it there.
  167.         //
  168.         for ( typename MessageContainer::iterator it = myFifo.begin();
  169.                 it != myFifo.end();
  170.                 ++it
  171.             )
  172.         {
  173.             // Assertion: The id for a timed event is just the
  174.             // address of the memory for the message. If this isn't
  175.             // true in TimerEntry, then we have problems.
  176.             //
  177.             if ( id == (EventId)((*it).operator->()) )
  178.             {
  179.                 myFifo.erase(it);
  180.                 return ;
  181.             }
  182.         }
  183.     }
  184. }
  185. template <class Msg>
  186. int
  187. FifoBase<Msg>::block(milliseconds_t relativeTimeout)
  188. throw ( VException )
  189. {
  190.     Lock lock(myMutex); (void)lock;
  191.     if ( messageAvailableNoLock() )
  192.     {
  193.         return ( 1 );
  194.     }
  195.     return ( blockNoLock(relativeTimeout) );
  196. }
  197. template <class Msg>
  198. Msg
  199. FifoBase<Msg> ::getNext()
  200. throw ( VException )
  201. {
  202.     Lock lock(myMutex); (void)lock;
  203.     // Wait while there are no messages available.
  204.     //
  205.     while ( !messageAvailableNoLock() )
  206.     {
  207.         blockNoLock();
  208.     }
  209.     // Move expired timers into fifo.
  210.     //
  211.     while ( myTimer.messageAvailable() )
  212.     {
  213.         try
  214.         {
  215.             myFifo.push_back(myTimer.getMessage());
  216.         }
  217.         catch ( ... )
  218.         {
  219.             assert(0);
  220.         }
  221.     }
  222.     // Return the first message on the fifo.
  223.     //
  224.     Msg firstMessage = *(myFifo.front());
  225.     myFifo.pop_front();
  226.     return ( firstMessage );
  227. }
  228. template <class Msg>
  229. unsigned int
  230. FifoBase<Msg> ::size() const
  231. {
  232.     Lock lock(myMutex); (void)lock;
  233.     return ( myFifo.size() + myTimer.size() );
  234. }
  235. template <class Msg>
  236. unsigned int 
  237. FifoBase<Msg>::sizeAvailable() const
  238. {
  239.     Lock lock(myMutex); (void)lock;
  240.     
  241.     return ( myFifo.size() );
  242. }
  243. template <class Msg>
  244. unsigned int 
  245. FifoBase<Msg>::sizePending() const
  246. {
  247.     Lock lock(myMutex); (void)lock;
  248.     
  249.     return ( myTimer.size() );
  250. }
  251. template <class Msg>
  252. bool
  253. FifoBase<Msg>::messageAvailable()
  254. {
  255.     Lock lock(myMutex); (void)lock;
  256.     
  257.     return ( messageAvailableNoLock() );
  258. }
  259. template <class Msg>
  260. void
  261. FifoBase<Msg>::shutdown()
  262. {
  263.     Lock lock(myMutex); (void)lock;
  264.     
  265.     myShutdown = true;
  266. }
  267. template<class Msg>
  268. bool
  269. FifoBase<Msg>::operator==(const FifoBase & src) const
  270. {
  271.     // Since each oberver is unique, we can compare addresses.
  272.     //
  273.     return ( this == &src );
  274. }
  275. template <class Msg>
  276. bool
  277. FifoBase<Msg>::operator!=(const FifoBase & src) const
  278. {
  279.     return ( this != &src );
  280. }
  281. template <class Msg>
  282. bool
  283. FifoBase<Msg>::operator<(const FifoBase & src) const
  284. {
  285.     return ( this < &src );
  286. }
  287. template <class Msg>
  288. bool
  289. FifoBase<Msg>::operator<=(const FifoBase & src) const
  290. {
  291.     return ( this <= &src );
  292. }
  293. template <class Msg>
  294. bool
  295. FifoBase<Msg>::operator>(const FifoBase & src) const
  296. {
  297.     return ( this > &src );
  298. }
  299. template <class Msg>
  300. bool
  301. FifoBase<Msg>::operator>=(const FifoBase & src) const
  302. {
  303.     return ( this >= &src );
  304. }
  305. template <class Msg>
  306. bool
  307. FifoBase<Msg>::messageAvailableNoLock()
  308. {
  309.     return ( myFifo.size() > 0 || myTimer.messageAvailable() );
  310. }
  311. template <class Msg>
  312. int
  313. FifoBase<Msg>::blockNoLock(milliseconds_t relativeTimeout)
  314. throw ( VException )
  315. {
  316.     // Use the shortest timeout value between the given relativeTimout
  317.     // and the timer container's timeout, remembering that infinite timeout
  318.     // is specified by a negative number.
  319.     //
  320.     milliseconds_t timerTimeout = myTimer.getTimeout(),
  321.                                   timeout;
  322.     // If timerTimeout is infinite, relativeTimeout can only be the
  323.     // same or shorter.
  324.     //
  325.     if ( timerTimeout < 0 )
  326.     {
  327.         timeout = relativeTimeout;
  328.     }
  329.     // If relativeTimeout is infinite, timerTimeout can only be the
  330.     // same or shorter.
  331.     //
  332.     else if ( relativeTimeout < 0 )
  333.     {
  334.         timeout = timerTimeout;
  335.     }
  336.     // Both are positive timeout values. Take the shortest in duration.
  337.     else
  338.     {
  339.         timeout = relativeTimeout < timerTimeout
  340.                   ? relativeTimeout
  341.                   : timerTimeout;
  342.     }
  343.     // Wait for an event. A timer expiry or signal will return a 0 here.
  344.     //
  345.     int numberActive = wait(timeout);
  346.     if ( numberActive > 0 )
  347.     {
  348.         return ( numberActive );
  349.     }
  350.     // See if a timer has expired.  If it has expired, return 1 to indicate
  351.     // a message is available from the timer.
  352.     //
  353.     if ( messageAvailableNoLock() )
  354.     {
  355.         return ( 1 );
  356.     }
  357.     // To get here, either a signal woke us up, or the we used the
  358.     // relativeTimeout value, meaning that a message isn't available from
  359.     // the timer container.
  360.     //
  361.     return ( 0 );
  362. }
  363. template <class Msg>
  364. void
  365. FifoBase<Msg>::postAddTimed(const EventId & newId)
  366.     TimerEntryId firstId = myTimer.getFirstTimerEntryId();
  367.     // If we insert the new message at the front of the timer list,
  368.     // we need to wakeup wait() since we have a timed message that
  369.     // expires sooner than the current, or if we didn't have a timer
  370.     // to begin with.
  371.     //
  372.     if ( firstId == newId )
  373.     {
  374.         try
  375.         {
  376.             wakeup();
  377.         }
  378.         catch ( VException & )
  379.         {
  380.             assert(0);
  381.         }
  382.     }
  383. }