root/trunk/libffado/src/libcontrol/Element.cpp

Revision 1158, 5.3 kB (checked in by ppalmers, 16 years ago)

make control more thread safe (unfinished)

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "Element.h"
25
26 #include "libutil/PosixMutex.h"
27
28 namespace Control {
29
30 IMPL_DEBUG_MODULE( Element, Element, DEBUG_LEVEL_NORMAL );
31
32 // This serves as an ID
33 // incremented on every Element creation
34 // ID's are unique as long as we don't create
35 // more than 2^64 elements.
36 // if we would create 1000 Elements per second
37 // we'd still need >500000 years to wrap.
38 // I guess we're safe.
39 static uint64_t GlobalElementCounter=0;
40
41 Element::Element(Element *parent)
42 : m_element_lock ( NULL )
43 , m_parent( parent )
44 , m_Name ( "NoName" )
45 , m_Label ( "No Label" )
46 , m_Description ( "No Description" )
47 , m_id(GlobalElementCounter++)
48 {
49     // no parent, we are the root of an independent control tree
50     // this means we have to create a lock
51     if(parent == NULL) {
52         m_element_lock = new Util::PosixMutex();
53     }
54 }
55
56 Element::Element(Element *parent, std::string n)
57 : m_element_lock ( NULL )
58 , m_parent( parent )
59 , m_Name( n )
60 , m_Label ( "No Label" )
61 , m_Description ( "No Description" )
62 , m_id(GlobalElementCounter++)
63 {
64     // no parent, we are the root of an independent control tree
65     // this means we have to create a lock
66     if(parent == NULL) {
67         m_element_lock = new Util::PosixMutex();
68     }
69 }
70
71 Element::~Element()
72 {
73     if(m_element_lock) delete m_element_lock;
74 }
75
76 void
77 Element::lockControl()
78 {
79     getLock().Lock();
80 }
81
82 void
83 Element::unlockControl()
84 {
85     getLock().Unlock();
86 }
87
88 Util::Mutex&
89 Element::getLock()
90 {
91     assert(m_parent != NULL || m_element_lock != NULL);
92     if(m_parent) {
93         return m_parent->getLock();
94     } else {
95         return *m_element_lock;
96     }
97 }
98
99 void
100 Element::show()
101 {
102     debugOutput( DEBUG_LEVEL_NORMAL, "Element %s\n",
103         getName().c_str());
104 }
105
106 void
107 Element::setVerboseLevel(int l)
108 {
109     setDebugLevel(l);
110     if(m_element_lock) m_element_lock->setVerboseLevel(l);
111     if(m_element_lock) m_element_lock->setVerboseLevel(DEBUG_LEVEL_VERY_VERBOSE);
112     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
113 }
114
115 //// --- Container --- ////
116 Container::Container(Element *p)
117 : Element(p)
118 {
119 }
120
121 Container::Container(Element *p, std::string n)
122 : Element(p, n)
123 {
124 }
125
126 unsigned int
127 Container::countElements()
128 {
129     lockControl();
130     unsigned int s = m_Children.size();
131     unlockControl();
132     return s;
133 }
134
135 const ElementVector &
136 Container::getElementVector()
137 {
138     lockControl();
139     return m_Children;
140 }
141
142 void
143 Container::releaseElementVector()
144 {
145     unlockControl();
146 }
147
148 bool
149 Container::addElement(Element *e)
150 {
151     Util::MutexLockHelper lock(getLock());
152     if (e==NULL) {
153         debugWarning("Cannot add NULL element\n");
154         return false;
155     }
156
157     debugOutput( DEBUG_LEVEL_VERBOSE, "Adding Element %s to %s\n",
158         e->getName().c_str(), getName().c_str());
159
160     // don't allow duplicates, only makes life hard
161     for ( ElementVectorIterator it = m_Children.begin();
162       it != m_Children.end();
163       ++it )
164     {
165         if(*it == e) {
166             debugOutput( DEBUG_LEVEL_VERBOSE, "Not adding Element %s, already present\n",
167                 e->getName().c_str());
168             return false;
169         }
170     }
171
172     m_Children.push_back(e);
173     return true;
174 }
175
176 bool
177 Container::deleteElement(Element *e)
178 {
179     Util::MutexLockHelper lock(getLock());
180     if(e == NULL) return false;
181     debugOutput( DEBUG_LEVEL_VERBOSE, "Deleting Element %s from %s\n",
182         e->getName().c_str(), getName().c_str());
183
184     for ( ElementVectorIterator it = m_Children.begin();
185       it != m_Children.end();
186       ++it )
187     {
188         if(*it == e) {
189             m_Children.erase(it);
190             return true;
191         }
192     }
193
194     debugOutput( DEBUG_LEVEL_VERBOSE, "Element %s not found \n",e->getName().c_str());
195     return false; //not found
196 }
197
198 bool
199 Container::clearElements(bool delete_pointers)
200 {
201     Util::MutexLockHelper lock(getLock());
202     while(m_Children.size()) {
203         Element *e=m_Children[0];
204         deleteElement(e);
205         if (delete_pointers) delete e;
206     }
207     return true;
208 }
209
210 void
211 Container::show()
212 {
213     Util::MutexLockHelper lock(getLock());
214     debugOutput( DEBUG_LEVEL_NORMAL, "Container %s (%d Elements)\n",
215         getName().c_str(), m_Children.size());
216
217     for ( ElementVectorIterator it = m_Children.begin();
218       it != m_Children.end();
219       ++it )
220     {
221         (*it)->show();
222     }
223 }
224
225 void
226 Container::setVerboseLevel(int l)
227 {
228     Util::MutexLockHelper lock(getLock());
229     setDebugLevel(l);
230     for ( ElementVectorIterator it = m_Children.begin();
231       it != m_Children.end();
232       ++it )
233     {
234         (*it)->setVerboseLevel(l);
235     }
236     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
237 }
238
239 } // namespace Control
Note: See TracBrowser for help on using the browser.