]> git.sesse.net Git - vlc/blob - modules/gui/skins2/commands/async_queue.cpp
de19dc7b3710fbb4921a1a8bd0cefac36021e98b
[vlc] / modules / gui / skins2 / commands / async_queue.cpp
1 /*****************************************************************************
2  * async_queue.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "async_queue.hpp"
26 #include "../src/os_factory.hpp"
27 #include "../src/os_timer.hpp"
28
29
30 AsyncQueue::AsyncQueue( intf_thread_t *pIntf ): SkinObject( pIntf ),
31     m_cmdFlush( this )
32 {
33     // Initialize the mutex
34     vlc_mutex_init( &m_lock );
35
36     // Create a timer
37     OSFactory *pOsFactory = OSFactory::instance( pIntf );
38     m_pTimer = pOsFactory->createOSTimer( m_cmdFlush );
39
40     // Flush the queue every 10 ms
41     m_pTimer->start( 10, false );
42 }
43
44
45 AsyncQueue::~AsyncQueue()
46 {
47     delete( m_pTimer );
48     vlc_mutex_destroy( &m_lock );
49 }
50
51
52 AsyncQueue *AsyncQueue::instance( intf_thread_t *pIntf )
53 {
54     if( ! pIntf->p_sys->p_queue )
55     {
56         AsyncQueue *pQueue;
57         pQueue = new AsyncQueue( pIntf );
58         if( pQueue )
59         {
60              // Initialization succeeded
61              pIntf->p_sys->p_queue = pQueue;
62         }
63      }
64      return pIntf->p_sys->p_queue;
65 }
66
67
68 void AsyncQueue::destroy( intf_thread_t *pIntf )
69 {
70     if( pIntf->p_sys->p_queue )
71     {
72         delete pIntf->p_sys->p_queue;
73         pIntf->p_sys->p_queue = NULL;
74     }
75 }
76
77
78 void AsyncQueue::push( const CmdGenericPtr &rcCommand, bool removePrev )
79 {
80     if( removePrev )
81     {
82         // Remove the commands of the same type
83         remove( rcCommand.get()->getType(), rcCommand );
84     }
85     m_cmdList.push_back( rcCommand );
86 }
87
88
89 void AsyncQueue::remove( const string &rType, const CmdGenericPtr &rcCommand )
90 {
91     vlc_mutex_lock( &m_lock );
92
93     list<CmdGenericPtr>::iterator it;
94     for( it = m_cmdList.begin(); it != m_cmdList.end(); it++ )
95     {
96         // Remove the command if it is of the given type
97         if( (*it).get()->getType() == rType )
98         {
99             // Maybe the command wants to check if it must really be
100             // removed
101             if( rcCommand.get()->checkRemove( (*it).get() ) == true )
102             {
103                 list<CmdGenericPtr>::iterator itNew = it;
104                 itNew++;
105                 m_cmdList.erase( it );
106                 it = itNew;
107             }
108         }
109     }
110
111     vlc_mutex_unlock( &m_lock );
112 }
113
114
115 void AsyncQueue::flush()
116 {
117     while (true)
118     {
119         vlc_mutex_lock( &m_lock );
120
121         if( m_cmdList.size() > 0 )
122         {
123             // Pop the first command from the queue
124             CmdGenericPtr cCommand = m_cmdList.front();
125             m_cmdList.pop_front();
126
127             // Unlock the mutex to avoid deadlocks if another thread wants to
128             // enqueue/remove a command while this one is processed
129             vlc_mutex_unlock( &m_lock );
130
131             // Execute the command
132             cCommand.get()->execute();
133         }
134         else
135         {
136             vlc_mutex_unlock( &m_lock );
137             break;
138         }
139     }
140 }
141
142
143 void AsyncQueue::CmdFlush::execute()
144 {
145     // Flush the queue
146     m_pParent->flush();
147 }