@@ -123,218 +123,219 @@ class QgsConnectionPoolGroup
123123 {
124124 qgsConnectionPool_ConnectionDestroy ( i.c );
125125 qgsConnectionPool_ConnectionCreate ( connInfo, i.c );
126+ }
126127
127128
128- // no need to run if nothing can expire
129- if ( conns.isEmpty () )
130- {
131- // will call the slot directly or queue the call (if the object lives in a different thread)
132- QMetaObject::invokeMethod ( expirationTimer->parent (), " stopExpirationTimer" );
133- }
134-
135- acquiredConns.append ( i.c );
136-
137- return i.c ;
129+ // no need to run if nothing can expire
130+ if ( conns.isEmpty () )
131+ {
132+ // will call the slot directly or queue the call (if the object lives in a different thread)
133+ QMetaObject::invokeMethod ( expirationTimer->parent (), " stopExpirationTimer" );
138134 }
139- }
140135
141- T c;
142- qgsConnectionPool_ConnectionCreate ( connInfo, c );
143- if ( !c )
144- {
145- // we didn't get connection for some reason, so release the lock
146- sem.release ();
147- return nullptr ;
148- }
136+ acquiredConns.append ( i.c );
149137
150- connMutex.lock ();
151- acquiredConns.append ( c );
152- connMutex.unlock ();
153- return c;
138+ return i.c ;
139+ }
154140 }
155141
156- void release ( T conn )
142+ T c;
143+ qgsConnectionPool_ConnectionCreate ( connInfo, c );
144+ if ( !c )
157145 {
158- connMutex.lock ();
159- acquiredConns.removeAll ( conn );
160- if ( !qgsConnectionPool_ConnectionIsValid ( conn ) )
161- {
162- qgsConnectionPool_ConnectionDestroy ( conn );
163- }
164- else
165- {
166- Item i;
167- i.c = conn;
168- i.lastUsedTime = QTime::currentTime ();
169- conns.push ( i );
170-
171- if ( !expirationTimer->isActive () )
172- {
173- // will call the slot directly or queue the call (if the object lives in a different thread)
174- QMetaObject::invokeMethod ( expirationTimer->parent (), " startExpirationTimer" );
175- }
176- }
146+ // we didn't get connection for some reason, so release the lock
147+ sem.release ();
148+ return nullptr ;
149+ }
177150
178- connMutex.unlock ();
151+ connMutex.lock ();
152+ acquiredConns.append ( c );
153+ connMutex.unlock ();
154+ return c;
155+ }
179156
180- sem.release (); // this can unlock a thread waiting in acquire()
157+ void release ( T conn )
158+ {
159+ connMutex.lock ();
160+ acquiredConns.removeAll ( conn );
161+ if ( !qgsConnectionPool_ConnectionIsValid ( conn ) )
162+ {
163+ qgsConnectionPool_ConnectionDestroy ( conn );
181164 }
182-
183- void invalidateConnections ()
165+ else
184166 {
185- connMutex.lock ();
186- for ( const Item &i : qgis::as_const ( conns ) )
167+ Item i;
168+ i.c = conn;
169+ i.lastUsedTime = QTime::currentTime ();
170+ conns.push ( i );
171+
172+ if ( !expirationTimer->isActive () )
187173 {
188- qgsConnectionPool_ConnectionDestroy ( i.c );
174+ // will call the slot directly or queue the call (if the object lives in a different thread)
175+ QMetaObject::invokeMethod ( expirationTimer->parent (), " startExpirationTimer" );
189176 }
190- conns.clear ();
191- for ( T c : qgis::as_const ( acquiredConns ) )
192- qgsConnectionPool_InvalidateConnection ( c );
193- connMutex.unlock ();
194177 }
195178
196- protected:
179+ connMutex. unlock ();
197180
198- void initTimer ( QObject * parent )
181+ sem.release (); // this can unlock a thread waiting in acquire()
182+ }
183+
184+ void invalidateConnections ()
185+ {
186+ connMutex.lock ();
187+ for ( const Item &i : qgis::as_const ( conns ) )
199188 {
200- expirationTimer = new QTimer ( parent );
201- expirationTimer->setInterval ( CONN_POOL_EXPIRATION_TIME * 1000 );
202- QObject::connect ( expirationTimer, SIGNAL ( timeout () ), parent, SLOT ( handleConnectionExpired () ) );
189+ qgsConnectionPool_ConnectionDestroy ( i.c );
190+ }
191+ conns.clear ();
192+ for ( T c : qgis::as_const ( acquiredConns ) )
193+ qgsConnectionPool_InvalidateConnection ( c );
194+ connMutex.unlock ();
195+ }
196+
197+ protected:
198+
199+ void initTimer ( QObject *parent )
200+ {
201+ expirationTimer = new QTimer ( parent );
202+ expirationTimer->setInterval ( CONN_POOL_EXPIRATION_TIME * 1000 );
203+ QObject::connect ( expirationTimer, SIGNAL ( timeout () ), parent, SLOT ( handleConnectionExpired () ) );
203204
204- // just to make sure the object belongs to main thread and thus will get events
205- if ( qApp )
206- parent->moveToThread ( qApp->thread () );
205+ // just to make sure the object belongs to main thread and thus will get events
206+ if ( qApp )
207+ parent->moveToThread ( qApp->thread () );
208+ }
209+
210+ void onConnectionExpired ()
211+ {
212+ connMutex.lock ();
213+
214+ QTime now = QTime::currentTime ();
215+
216+ // what connections have expired?
217+ QList<int > toDelete;
218+ for ( int i = 0 ; i < conns.count (); ++i )
219+ {
220+ if ( conns.at ( i ).lastUsedTime .secsTo ( now ) >= CONN_POOL_EXPIRATION_TIME )
221+ toDelete.append ( i );
207222 }
208223
209- void onConnectionExpired ()
224+ // delete expired connections
225+ for ( int j = toDelete.count () - 1 ; j >= 0 ; --j )
210226 {
211- connMutex.lock ();
227+ int index = toDelete[j];
228+ qgsConnectionPool_ConnectionDestroy ( conns[index].c );
229+ conns.remove ( index );
230+ }
212231
213- QTime now = QTime::currentTime ();
232+ if ( conns.isEmpty () )
233+ expirationTimer->stop ();
214234
215- // what connections have expired?
216- QList<int > toDelete;
217- for ( int i = 0 ; i < conns.count (); ++i )
218- {
219- if ( conns.at ( i ).lastUsedTime .secsTo ( now ) >= CONN_POOL_EXPIRATION_TIME )
220- toDelete.append ( i );
221- }
235+ connMutex.unlock ();
236+ }
222237
223- // delete expired connections
224- for ( int j = toDelete.count () - 1 ; j >= 0 ; --j )
225- {
226- int index = toDelete[j];
227- qgsConnectionPool_ConnectionDestroy ( conns[index].c );
228- conns.remove ( index );
229- }
238+ protected:
230239
231- if ( conns.isEmpty () )
232- expirationTimer->stop ();
240+ QString connInfo;
241+ QStack<Item> conns;
242+ QList<T> acquiredConns;
243+ QMutex connMutex;
244+ QSemaphore sem;
245+ QTimer *expirationTimer = nullptr ;
233246
234- connMutex.unlock ();
235- }
247+ };
236248
237- protected:
238249
239- QString connInfo;
240- QStack<Item> conns;
241- QList<T> acquiredConns;
242- QMutex connMutex;
243- QSemaphore sem;
244- QTimer *expirationTimer = nullptr ;
250+ /* *
251+ * \ingroup core
252+ * Template class responsible for keeping a pool of open connections.
253+ * This is desired to avoid the overhead of creation of new connection every time.
254+ *
255+ * The methods are thread safe.
256+ *
257+ * The connection pool has a limit on maximum number of concurrent connections
258+ * (per server), once the limit is reached, the acquireConnection() function
259+ * will block. All connections that have been acquired must be then released
260+ * with releaseConnection() function.
261+ *
262+ * When the connections are not used for some time, they will get closed automatically
263+ * to save resources.
264+ * \note not available in Python bindings
265+ */
266+ template <typename T, typename T_Group>
267+ class QgsConnectionPool
268+ {
269+ public:
245270
246- } ;
271+ typedef QMap<QString, T_Group *> T_Groups ;
247272
273+ virtual ~QgsConnectionPool ()
274+ {
275+ mMutex .lock ();
276+ for ( T_Group *group : qgis::as_const ( mGroups ) )
277+ {
278+ delete group;
279+ }
280+ mGroups .clear ();
281+ mMutex .unlock ();
282+ }
248283
249284 /* *
250- * \ingroup core
251- * Template class responsible for keeping a pool of open connections.
252- * This is desired to avoid the overhead of creation of new connection every time .
285+ * Try to acquire a connection for a maximum of \a timeout milliseconds.
286+ * If \a timeout is a negative value the calling thread will be blocked
287+ * until a connection becomes available. This is the default behavior .
253288 *
254- * The methods are thread safe.
255289 *
256- * The connection pool has a limit on maximum number of concurrent connections
257- * (per server), once the limit is reached, the acquireConnection() function
258- * will block. All connections that have been acquired must be then released
259- * with releaseConnection() function.
260290 *
261- * When the connections are not used for some time, they will get closed automatically
262- * to save resources.
263- * \note not available in Python bindings
291+ * \returns initialized connection or nullptr if unsuccessful
264292 */
265- template <typename T, typename T_Group>
266- class QgsConnectionPool
293+ T acquireConnection ( const QString &connInfo, int timeout = -1 , bool requestMayBeNested = false )
267294 {
268- public:
269-
270- typedef QMap<QString, T_Group *> T_Groups;
271-
272- virtual ~QgsConnectionPool ()
273- {
274- mMutex .lock ();
275- for ( T_Group *group : qgis::as_const ( mGroups ) )
276- {
277- delete group;
278- }
279- mGroups .clear ();
280- mMutex .unlock ();
281- }
282-
283- /* *
284- * Try to acquire a connection for a maximum of \a timeout milliseconds.
285- * If \a timeout is a negative value the calling thread will be blocked
286- * until a connection becomes available. This is the default behavior.
287- *
288- *
289- *
290- * \returns initialized connection or nullptr if unsuccessful
291- */
292- T acquireConnection ( const QString &connInfo, int timeout = -1 , bool requestMayBeNested = false )
293- {
294- mMutex .lock ();
295- typename T_Groups::iterator it = mGroups .find ( connInfo );
296- if ( it == mGroups .end () )
297- {
298- it = mGroups .insert ( connInfo, new T_Group ( connInfo ) );
299- }
300- T_Group *group = *it;
301- mMutex .unlock ();
295+ mMutex .lock ();
296+ typename T_Groups::iterator it = mGroups .find ( connInfo );
297+ if ( it == mGroups .end () )
298+ {
299+ it = mGroups .insert ( connInfo, new T_Group ( connInfo ) );
300+ }
301+ T_Group *group = *it;
302+ mMutex .unlock ();
302303
303- return group->acquire ( timeout, requestMayBeNested );
304- }
304+ return group->acquire ( timeout, requestMayBeNested );
305+ }
305306
306- // ! Release an existing connection so it will get back into the pool and can be reused
307- void releaseConnection ( T conn )
308- {
309- mMutex .lock ();
310- typename T_Groups::iterator it = mGroups .find ( qgsConnectionPool_ConnectionToName ( conn ) );
311- Q_ASSERT ( it != mGroups .end () );
312- T_Group *group = *it;
313- mMutex .unlock ();
307+ // ! Release an existing connection so it will get back into the pool and can be reused
308+ void releaseConnection ( T conn )
309+ {
310+ mMutex .lock ();
311+ typename T_Groups::iterator it = mGroups .find ( qgsConnectionPool_ConnectionToName ( conn ) );
312+ Q_ASSERT ( it != mGroups .end () );
313+ T_Group *group = *it;
314+ mMutex .unlock ();
314315
315- group->release ( conn );
316- }
316+ group->release ( conn );
317+ }
317318
318- /* *
319- * Invalidates all connections to the specified resource.
320- * The internal state of certain handles (for instance OGR) are altered
321- * when a dataset is modified. Consquently, all open handles need to be
322- * invalidated when such datasets are changed to ensure the handles are
323- * refreshed. See the OGR provider for an example where this is needed.
324- */
325- void invalidateConnections ( const QString &connInfo )
326- {
327- mMutex .lock ();
328- if ( mGroups .contains ( connInfo ) )
329- mGroups [connInfo]->invalidateConnections ();
330- mMutex .unlock ();
331- }
319+ /* *
320+ * Invalidates all connections to the specified resource.
321+ * The internal state of certain handles (for instance OGR) are altered
322+ * when a dataset is modified. Consquently, all open handles need to be
323+ * invalidated when such datasets are changed to ensure the handles are
324+ * refreshed. See the OGR provider for an example where this is needed.
325+ */
326+ void invalidateConnections ( const QString &connInfo )
327+ {
328+ mMutex .lock ();
329+ if ( mGroups .contains ( connInfo ) )
330+ mGroups [connInfo]->invalidateConnections ();
331+ mMutex .unlock ();
332+ }
332333
333334
334- protected:
335- T_Groups mGroups ;
336- QMutex mMutex ;
337- };
335+ protected:
336+ T_Groups mGroups ;
337+ QMutex mMutex ;
338+ };
338339
339340
340341#endif // QGSCONNECTIONPOOL_H
0 commit comments