[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/nepomuk/query
From:       Sebastian Trueg <sebastian () trueg ! de>
Date:       2011-01-16 11:37:45
Message-ID: 20110116113745.D44973E1F1 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1214784 by trueg:

* Static non-PODs are evil - use a poll for all the preparsed QRexExp.
* Protect the fieldCache with a mutex to make the QueryParser completely thread-safe

 M  +84 -39    queryparser.cpp  


--- trunk/KDE/kdelibs/nepomuk/query/queryparser.cpp #1214783:1214784
@@ -31,6 +31,8 @@
 
 #include <QtCore/QRegExp>
 #include <QtCore/QSet>
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
 
 #include <kdebug.h>
 #include <klocale.h>
@@ -48,40 +50,6 @@
 using namespace Nepomuk::Query;
 
 namespace {
-    // a field differs from a plain term in that it does never allow comparators
-    QString s_fieldNamePattern( "([^\\s\"':=<>]+|(?:([\"'])[^\"':=<>]+\\%1))" );
-    QString s_plainTermPattern( "([^\\s\"':=<>]+|(?:([\"'])[^\"']+\\%1))" );
-    QString s_inExclusionPattern( "([\\+\\-]?)" );
-    QString s_uriPattern( "<([^<>]+)>" );
-    QString s_comparatorPattern( "(:|\\<=|\\>=|=|\\<|\\>)" );
-
-    // match a simple search text
-    // captures: 1 - The optional + or - sign (may be empty)
-    //           2 - the search text (including optional paranthesis)
-    QRegExp s_plainTermRx( s_inExclusionPattern + s_plainTermPattern.arg( 3 ) );
-
-    // match a field search term: fieldname + relation (:, =, etc) + search text \
                with optional paranthesis
-    // captures: 1 - The optional + or - sign (may be empty)
-    //           2 - fieldname
-    //           3 - relation
-    //           4 - search text (including optional paranthesis)
-    QRegExp s_fieldRx( s_inExclusionPattern + s_fieldNamePattern.arg( 3 ) + \
                s_comparatorPattern + s_plainTermPattern.arg( 6 ) );
-
-    // match a property URI search term: property URI + relation (:, =, etc) + \
                search text with optional paranthesis
-    // captures: 1 - The optional + or - sign (may be empty)
-    //           2 - property URI
-    //           3 - relation
-    //           4 - search text (including optional paranthesis)
-    QRegExp s_propertyRx( s_inExclusionPattern + s_uriPattern + s_comparatorPattern \
                + s_plainTermPattern.arg( 5 ) );
-
-    // match a property URI search term: property URI + relation (:, =, etc) + \
                resource URI
-    // captures: 1 - The optional + or - sign (may be empty)
-    //           2 - property URI
-    //           3 - resource URI
-    QRegExp s_resourceRx( s_inExclusionPattern + s_uriPattern + "(?::|=)" + \
                s_uriPattern );
-
-    QRegExp s_fieldFieldRx( s_inExclusionPattern + s_fieldNamePattern.arg( 3 ) + \
s_comparatorPattern + "\\(" +  s_fieldNamePattern.arg( 6 ) + s_comparatorPattern + \
                s_plainTermPattern.arg( 9 ) + "\\)" );
-
     Nepomuk::Query::ComparisonTerm::Comparator fieldTypeRelationFromString( const \
QString& s ) {  if ( s == "=" ) {
             return Nepomuk::Query::ComparisonTerm::Equal;
@@ -358,15 +326,87 @@
         }
     }
 #endif
+
+    // a field differs from a plain term in that it does never allow comparators
+    const char* s_fieldNamePattern = "([^\\s\"':=<>]+|(?:([\"'])[^\"':=<>]+\\%1))";
+    const char* s_plainTermPattern = "([^\\s\"':=<>]+|(?:([\"'])[^\"']+\\%1))";
+    const char* s_inExclusionPattern = "([\\+\\-]?)";
+    const char* s_uriPattern = "<([^<>]+)>";
+    const char* s_comparatorPattern = "(:|\\<=|\\>=|=|\\<|\\>)";
+
+    /**
+     * Creating QRegExp is expensive, copying them is cheap. Thus, we keep static
+     * instances of the regexps around which we only have to create once.
+     */
+    class QueryParserRegExpPool
+    {
+    public:
+        QueryParserRegExpPool()
+            : plainTermRx( QLatin1String(s_inExclusionPattern)
+                  + QString::fromLatin1(s_plainTermPattern).arg( 3 ) ),
+              fieldRx( QLatin1String(s_inExclusionPattern)
+                  + QString::fromLatin1(s_fieldNamePattern).arg( 3 )
+                  + QLatin1String(s_comparatorPattern)
+                  + QString::fromLatin1(s_plainTermPattern).arg( 6 ) ),
+              propertyRx( QLatin1String(s_inExclusionPattern)
+                  + QLatin1String(s_uriPattern)
+                  + QLatin1String(s_comparatorPattern)
+                  + QString::fromLatin1(s_plainTermPattern).arg( 5 ) ),
+              resourceRx( QLatin1String(s_inExclusionPattern)
+                  + QLatin1String(s_uriPattern)
+                  + QLatin1String("(?::|=)")
+                  + QLatin1String(s_uriPattern) ),
+              fieldFieldRx( QLatin1String(s_inExclusionPattern)
+                  + QString::fromLatin1(s_fieldNamePattern).arg( 3 )
+                  + QLatin1String(s_comparatorPattern)
+                  + QLatin1String("\\(")
+                  +  QString::fromLatin1(s_fieldNamePattern).arg( 6 )
+                  + QLatin1String(s_comparatorPattern)
+                  + QString::fromLatin1(s_plainTermPattern).arg( 9 )
+                  + QLatin1String("\\)") )
+        {
 }
 
+        // match a simple search text
+        // captures: 1 - The optional + or - sign (may be empty)
+        //           2 - the search text (including optional paranthesis)
+        QRegExp plainTermRx;
 
+        // match a field search term: fieldname + relation (:, =, etc) + search text \
with optional paranthesis +        // captures: 1 - The optional + or - sign (may be \
empty) +        //           2 - fieldname
+        //           3 - relation
+        //           4 - search text (including optional paranthesis)
+        QRegExp fieldRx;
+
+        // match a property URI search term: property URI + relation (:, =, etc) + \
search text with optional paranthesis +        // captures: 1 - The optional + or - \
sign (may be empty) +        //           2 - property URI
+        //           3 - relation
+        //           4 - search text (including optional paranthesis)
+        QRegExp propertyRx;
+
+        // match a property URI search term: property URI + relation (:, =, etc) + \
resource URI +        // captures: 1 - The optional + or - sign (may be empty)
+        //           2 - property URI
+        //           3 - resource URI
+        QRegExp resourceRx;
+
+        QRegExp fieldFieldRx;
+    };
+
+    // the one global instance used for the statis QueryParser methods
+    K_GLOBAL_STATIC( QueryParserRegExpPool, s_regExpPool )
+}
+
+
 class Nepomuk::Query::QueryParser::Private
 {
 public:
     QSet<QString> andKeywords;
     QSet<QString> orKeywords;
     mutable QHash<QString, QList<Types::Property> > fieldMatchCache;
+    QMutex fieldMatchCacheMutex;
 };
 
 
@@ -404,11 +444,15 @@
 {
     kDebug() << fieldName;
 
+    QMutexLocker lock( &d->fieldMatchCacheMutex );
+
     QHash<QString, QList<Types::Property> >::ConstIterator it = \
d->fieldMatchCache.constFind( fieldName );  if( it != d->fieldMatchCache.constEnd() ) \
{  return it.value();
     }
     else {
+        lock.unlock();
+
         QList<Nepomuk::Types::Property> results;
 
         //
@@ -437,6 +481,7 @@
             kDebug() << "Found property match" << property;
         }
 
+        lock.relock();
         d->fieldMatchCache.insert( fieldName, results );
         return results;
     }
@@ -463,11 +508,11 @@
     int pos = 0;
 
     // create local copies of the regexps for thread safety purposes
-    const QRegExp resourceRx = s_resourceRx;
-    const QRegExp propertyRx = s_propertyRx;
-    const QRegExp fieldFieldRx = s_fieldFieldRx;
-    const QRegExp fieldRx = s_fieldRx;
-    const QRegExp plainTermRx = s_plainTermRx;
+    const QRegExp resourceRx = s_regExpPool->resourceRx;
+    const QRegExp propertyRx = s_regExpPool->propertyRx;
+    const QRegExp fieldFieldRx = s_regExpPool->fieldFieldRx;
+    const QRegExp fieldRx = s_regExpPool->fieldRx;
+    const QRegExp plainTermRx = s_regExpPool->plainTermRx;
 
     while ( pos < query.length() ) {
         // skip whitespace


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic