]> git.sesse.net Git - vlc/blob - modules/gui/skins2/commands/async_queue.cpp
Move MODULE_* predefined constants from vlc-config to Makefile
[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     delete pIntf->p_sys->p_queue;
71     pIntf->p_sys->p_queue = NULL;
72 }
73
74
75 void AsyncQueue::push( const CmdGenericPtr &rcCommand, bool removePrev )
76 {
77     vlc_mutex_lock( &m_lock );
78
79     if( removePrev )
80     {
81         // Remove the commands of the same type
82         remove( rcCommand.get()->getType(), rcCommand );
83     }
84     m_cmdList.push_back( rcCommand );
85
86     vlc_mutex_unlock( &m_lock );
87 }
88
89
90 void AsyncQueue::remove( const string &rType, const CmdGenericPtr &rcCommand )
91 {
92     cmdList_t::iterator it;
93     for( it = m_cmdList.begin(); it != m_cmdList.end(); /* nothing */ )
94     {
95         // Remove the command if it is of the given type and the command
96         // doesn't disagree. Note trickery to avoid skipping entries
97         // while maintaining iterator validity.
98
99         if( (*it).get()->getType() == rType &&
100             rcCommand.get()->checkRemove( (*it).get() ) )
101         {
102             cmdList_t::iterator itNew = it;
103             ++itNew;
104             m_cmdList.erase( it );
105             it = itNew;
106         }
107         else ++it;
108     }
109 }
110
111
112 void AsyncQueue::flush()
113 {
114     while (true)
115     {
116         vlc_mutex_lock( &m_lock );
117
118         if( m_cmdList.size() > 0 )
119         {
120             // Pop the first command from the queue
121             CmdGenericPtr cCommand = m_cmdList.front();
122             m_cmdList.pop_front();
123
124             // Unlock the mutex to avoid deadlocks if another thread wants to
125             // enqueue/remove a command while this one is processed
126             vlc_mutex_unlock( &m_lock );
127
128             // Execute the command
129             cCommand.get()->execute();
130         }
131         else
132         {
133             vlc_mutex_unlock( &m_lock );
134             break;
135         }
136     }
137 }
138
139
140 void AsyncQueue::CmdFlush::execute()
141 {
142     // Flush the queue
143     m_pParent->flush();
144 }