Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 4

Qt-interest Archive, December 2007
How to yield execution to main messageloop?


Message 1 in thread

Hello,

I am developing a small logging component which consists of two parts. A small application, the logreciever, which reads a shared memory with log messages and a small class which can be put in any qt-app that should do logging.

when there are many log entries it could be happen, that the shared memory is full. so the logger class has to wait until the logreciever application has processed all log entries. Since I have no Qthread in the logger class I have no uSleep or something like this. the only thing I found was QObject::thread()->wait(). But this doesn't work.

while (buffer->nextPosition == MESSAGE_LIST_SIZE)
{
	// Messagelist full
	sm_logout.unlock();
	thread()->wait(100);   // will not wait and throws a warning QThread::wait: Thread tried to wait on itself
	sm_logout.lock();
}

So how can I make my function to yield executen to the Application Messageloop for a number of ms?

--
 [ signature omitted ] 

Message 2 in thread

You have a standard mutual exclusion problem here. You can't use the Qt 
classes for this, since they work inside a single application space. I did 
consider using a placement new on QMutex inside the shared memory space, but 
I don't know if this would work, so I assume not.

The problem is solved several times in computer science. The one I have tried 
implementing before was Lamports solution. I found the article about this one 
here: http://research.microsoft.com/users/lamport/pubs/fast-mutex.ps.

Bo.

On torsdag den 20. December 2007, Wente, Andreas wrote:
> Hello,
>
> I am developing a small logging component which consists of two parts. A
> small application, the logreciever, which reads a shared memory with log
> messages and a small class which can be put in any qt-app that should do
> logging.
>
> when there are many log entries it could be happen, that the shared memory
> is full. so the logger class has to wait until the logreciever application
> has processed all log entries. Since I have no Qthread in the logger class
> I have no uSleep or something like this. the only thing I found was
> QObject::thread()->wait(). But this doesn't work.
>
> while (buffer->nextPosition == MESSAGE_LIST_SIZE)
> {
> 	// Messagelist full
> 	sm_logout.unlock();
> 	thread()->wait(100);   // will not wait and throws a warning
> QThread::wait: Thread tried to wait on itself sm_logout.lock();
> }
>
> So how can I make my function to yield executen to the Application
> Messageloop for a number of ms?
>
> --
> Mit freundlichen Grüßen / kind regards,
>
> Andreas Wente
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/



-- 
 [ signature omitted ] 

Message 3 in thread

Bo Thorsen wrote:
>You have a standard mutual exclusion problem here. You can't use the Qt
>classes for this, since they work inside a single application space. I
> did consider using a placement new on QMutex inside the shared memory
> space, but I don't know if this would work, so I assume not.

http://doc.trolltech.com/main-snapshot/qsystemsemaphore.html

New in Qt 4.4.
-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 4 in thread

> Bo Thorsen wrote:
> >You have a standard mutual exclusion problem here. You can't use the Qt
> >classes for this, since they work inside a single application space. I
> >did consider using a placement new on QMutex inside the shared memory
> >space, but I don't know if this would work, so I assume not.
> 
> http://doc.trolltech.com/main-snapshot/qsystemsemaphore.html
> 
> New in Qt 4.4.

Hmm... A system mutex or semaphore don't seem to be the right thing for my problem. Because the logger class has to wait even if the shared memory is _not_ locked by the receiver. For example when there is heavy logging, the independent loggers fill the shared memory and when it is full they have to wait until the logreciever empties it. This is done in a defined interval.

So again. How can I wait in a CPU Resource saving way. 

I think this
			while (buffer->nextPosition == MESSAGE_LIST_SIZE)
			{
				// Messagelist full
				sm_logout.unlock();
				QCoreApplication::processEvents();
				sm_logout.lock();
			}

is no good choice, because of the very frequent unlock-lock of the shared memory.

--
 [ signature omitted ] 

Message 5 in thread

On torsdag den 20. December 2007, Wente, Andreas wrote:
> > Bo Thorsen wrote:
> > >You have a standard mutual exclusion problem here. You can't use the Qt
> > >classes for this, since they work inside a single application space. I
> > >did consider using a placement new on QMutex inside the shared memory
> > >space, but I don't know if this would work, so I assume not.
> >
> > http://doc.trolltech.com/main-snapshot/qsystemsemaphore.html
> >
> > New in Qt 4.4.

Nice :)

> Hmm... A system mutex or semaphore don't seem to be the right thing for my
> problem. Because the logger class has to wait even if the shared memory is
> _not_ locked by the receiver. For example when there is heavy logging, the
> independent loggers fill the shared memory and when it is full they have to
> wait until the logreciever empties it. This is done in a defined interval.
>
> So again. How can I wait in a CPU Resource saving way.
>
> I think this
> 			while (buffer->nextPosition == MESSAGE_LIST_SIZE)
> 			{
> 				// Messagelist full
> 				sm_logout.unlock();
> 				QCoreApplication::processEvents();
> 				sm_logout.lock();
> 			}
>
> is no good choice, because of the very frequent unlock-lock of the shared
> memory.

Here's the big question: Where should a log client write to? Locking the log 
area is impossible to avoid unless you want race conditions.

If you're worried about the performance of the log clients, just put the 
writing in a thread. If you're worried about performance of the log server, 
make more than one shared memory log.

Bo.

-- 
 [ signature omitted ] 

Message 6 in thread

> Here's the big question: Where should a log client write to? Locking the
> log
> area is impossible to avoid unless you want race conditions.
> 
> If you're worried about the performance of the log clients, just put the
> writing in a thread. If you're worried about performance of the log server,
> make more than one shared memory log.

That's the point. I want to keep the log-class as small and performant as possible. So I don't want to use a extra thread for each logger. In case of very heavy logging I can live with litte waitingtimes.

The workflow looks like this:

logger:
	- get logmessage
	- while sharememory is full
		- sleep 10ms 			<-- The problem
	- append log to shared memory

reciever:
	- forever
		- sleep 10ms
		- lock sharedmemory
		- copy sharedmemory
		- unlock sharedmemory
		- write log to sqlite-db
	

--
 [ signature omitted ] 

Message 7 in thread

Wente, Andreas wrote:
>logger:
>        - get logmessage
>        - while sharememory is full
>                - sleep 10ms                    <-- The problem
>        - append log to shared memory
>
>reciever:
>        - forever
>                - sleep 10ms
>                - lock sharedmemory
>                - copy sharedmemory
>                - unlock sharedmemory
>                - write log to sqlite-db

Your receiver is waiting 10 ms too much.

It shouldn't wait at all if there's data available. But it must not 
busy-wait. Therefore you need a way of being notified immediately 
whenever there's data available, but sleep for as long as you need when 
there isn't.

We're talking about QSystemSemaphore or QLocalSocket.
-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 8 in thread

 
> Wente, Andreas wrote:
> >logger:
> >        - get logmessage
> >        - while sharememory is full
> >                - sleep 10ms                    <-- The problem
> >        - append log to shared memory
> >
> >reciever:
> >        - forever
> >                - sleep 10ms
> >                - lock sharedmemory
> >                - copy sharedmemory
> >                - unlock sharedmemory
> >                - write log to sqlite-db
> 
> Your receiver is waiting 10 ms too much.
> 
> It shouldn't wait at all if there's data available. But it must not busy-
> wait. Therefore you need a way of being notified immediately whenever
> there's data available, but sleep for as long as you need when there isn't.
> 

I don't think so. The sharedmemory could contain up to 1000 Logmessages. And there are many loggers. So the chance to get a blocking lock is greater when the receiver reads the sharedmemory as soon as a message is in. So he will read it in an intervall, fetches all messages and store them in sqlite within one transaction. doing this for every message will slow things down, I think.

--
 [ signature omitted ] 

Message 9 in thread

Wente, Andreas wrote:
>I don't think so. The sharedmemory could contain up to 1000 Logmessages.
> And there are many loggers. So the chance to get a blocking lock is
> greater when the receiver reads the sharedmemory as soon as a message
> is in. So he will read it in an intervall, fetches all messages and
> store them in sqlite within one transaction. doing this for every
> message will slow things down, I think.

It's easy to do this with a socket and a timeout writing to the database, 
or if you reach critical mass.

No blocking.
-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 10 in thread

Wente, Andreas wrote:
>> Bo Thorsen wrote:
>> >You have a standard mutual exclusion problem here. You can't use the
>> > Qt classes for this, since they work inside a single application
>> > space. I did consider using a placement new on QMutex inside the
>> > shared memory space, but I don't know if this would work, so I
>> > assume not.
>>
>> http://doc.trolltech.com/main-snapshot/qsystemsemaphore.html
>>
>> New in Qt 4.4.
>
>Hmm... A system mutex or semaphore don't seem to be the right thing for
> my problem. Because the logger class has to wait even if the shared
> memory is _not_ locked by the receiver. For example when there is heavy
> logging, the independent loggers fill the shared memory and when it is
> full they have to wait until the logreciever empties it. This is done
> in a defined interval.
>
>So again. How can I wait in a CPU Resource saving way.
>
>I think this
>			while (buffer->nextPosition == MESSAGE_LIST_SIZE)
>			{
>				// Messagelist full
>				sm_logout.unlock();
>				QCoreApplication::processEvents();
>				sm_logout.lock();
>			}
>
>is no good choice, because of the very frequent unlock-lock of the
> shared memory.

Your log queue is a shared resource with a limited size. It's a typical 
producer-consumer case, except it's run in multiple processes. When the 
producer tries to acquire a resource that isn't available, it'll sleep 
until there's a resource.

Otherwise, use QLocalSocket to transfer the log data from the producers to 
the consumers, without blocking.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.