radioapp/radiouiengine/src/radiotimerpool.cpp
changeset 57 21be958eb3ce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/radioapp/radiouiengine/src/radiotimerpool.cpp	Fri Oct 15 16:26:27 2010 +0300
@@ -0,0 +1,196 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+// System includes
+#include <QTimer>
+#include <QMetaMethod>
+
+// User includes
+#include "radiotimerpool.h"
+#include "radiologger.h"
+
+const int TIMER_BUFFER_SIZE = 2;
+
+/*!
+ *
+ */
+RadioTimerPool::RadioTimerItem::RadioTimerItem( RadioTimerPool* parent ) :
+    mTimer( new QTimer() )
+{
+    Radio::connect( mTimer.data(),  SIGNAL(timeout()),
+                    parent,         SLOT(timerFired()) );
+    mTimer->setSingleShot( true );
+}
+
+/*!
+ *
+ */
+RadioTimerPool::RadioTimerItem::~RadioTimerItem()
+{
+}
+
+/*!
+ *
+ */
+void RadioTimerPool::RadioTimerItem::reset()
+{
+    mTimer->stop();
+    mId = -1;
+    mParam = QVariant();
+    mReceiver = NULL;
+    mReceiverMember.clear();
+}
+
+/*!
+ *
+ */
+RadioTimerPool::RadioTimerPool( QObject* parent ) :
+    QObject( parent )
+{
+    createItem();
+}
+
+/*!
+ *
+ */
+RadioTimerPool::~RadioTimerPool()
+{
+    qDeleteAll( mTimerMap.values() );
+}
+
+/*!
+ *
+ */
+void RadioTimerPool::startTimer( int msec, int id, QObject* receiver, const char* member, QVariant param )
+{
+    LOG_METHOD;
+    RadioTimerItem* availableItem = NULL;
+    foreach ( RadioTimerItem* item, mTimerMap.values() ) {
+        if ( !item->mTimer->isActive() ) {
+            availableItem = item;
+        } else {
+            if ( item->mReceiver == receiver && item->mId == id ) {
+                LOG_FORMAT( "RadioTimerPool::startTimer. Timer %d already running for class %s", id, receiver->metaObject()->className() );
+            }
+        }
+    }
+
+    if ( !availableItem ) {
+        availableItem = createItem();
+        LOG( "RadioTimerPool::startTimer. Creating new timer" );
+    }
+    LOG_FORMAT( "Amount of timers: %d", mTimerMap.count() );
+
+    availableItem->mId = id;
+    availableItem->mParam = param;
+    availableItem->mReceiver = receiver;
+
+    // SIGNAL() and SLOT() macros add a number in the beginning of member function name for some internal housekeeping
+    // That causes the method to not be found from the meta object so we need to trim it off
+    availableItem->mReceiverMember = member;
+    availableItem->mReceiverMember = availableItem->mReceiverMember.right( availableItem->mReceiverMember.length() - 1 );
+
+    availableItem->mTimer->start( msec );
+}
+
+/*!
+ *
+ */
+void RadioTimerPool::cancelTimer( int id, const QObject* receiver )
+{
+    foreach ( RadioTimerItem* item, mTimerMap.values() ) {
+        if ( item->mId == id && item->mReceiver == receiver ) {
+            item->reset();
+            break;
+        }
+    }
+    freeUnusedTimers();
+}
+
+/*!
+ *
+ */
+bool RadioTimerPool::isTimerActive( int id, const QObject* receiver ) const
+{
+    foreach ( const RadioTimerItem* item, mTimerMap.values() ) {
+        if ( item->mId == id &&
+             item->mReceiver == receiver &&
+             item->mTimer->isActive() ) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*!
+ *
+ */
+void RadioTimerPool::freeUnusedTimers()
+{
+    QList<RadioTimerItem*> unusedItems;
+    foreach ( RadioTimerItem* item, mTimerMap.values() ) {
+        if ( !item->mTimer->isActive() ) {
+            unusedItems.append( item );
+        }
+    }
+
+    if ( unusedItems.count() > TIMER_BUFFER_SIZE ) {
+        foreach( const RadioTimerItem* item, unusedItems ) {
+            mTimerMap.remove( item->mTimer.data() );
+            delete item;
+        }
+    }
+}
+
+/*!
+ * Private slot
+ */
+void RadioTimerPool::timerFired()
+{
+    QTimer* timer = static_cast<QTimer*>( sender() );
+    if ( mTimerMap.contains( timer ) ) {
+        RadioTimerItem* item = mTimerMap.value( timer );
+        if ( item->mReceiver ) {
+            QByteArray normalizedSignature = QMetaObject::normalizedSignature( item->mReceiverMember.toAscii().constData() );
+            int methodIndex = item->mReceiver->metaObject()->indexOfMethod( normalizedSignature );
+            if ( methodIndex != -1 ) {
+                QMetaMethod method = item->mReceiver->metaObject()->method( methodIndex );
+                const int paramCount = method.parameterTypes().count();
+                if ( paramCount == 0 ) {
+                    method.invoke( item->mReceiver, Qt::QueuedConnection );
+                } else if ( paramCount == 1 ) {
+                    method.invoke( item->mReceiver, Qt::QueuedConnection, Q_ARG( int, item->mId ) );
+                } else if ( paramCount == 2 ) {
+                    method.invoke( item->mReceiver, Qt::QueuedConnection,
+                                   Q_ARG( int, item->mId ), Q_ARG( QVariant, item->mParam ) );
+                }
+            }
+
+            item->reset();
+        }
+    }
+}
+
+/*!
+ *
+ */
+RadioTimerPool::RadioTimerItem* RadioTimerPool::createItem()
+{
+    RadioTimerItem* item = new RadioTimerItem( this );
+    mTimerMap.insert( item->mTimer.data(), item );
+    return item;
+}