Close blocking QLocalServer from other thread - qt

I am running a blocking QLocalServer in a thread:
void QThread::stopServer()
{
m_abort = true;
m_server.close(); // QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
}
void QThread::run()
{
m_server = new QLocalServer();
m_server->Listen("PipeName");
while (!m_abort)
{
if (m_server->waitForNewConnection())
{
// handle the connection
}
}
delete m_server;
}
How can the server be closed from another thread? Or is the only way to use non-blocking events?
Regards,

Why just not wait until run() closes or deletes the connection itself, after m_abort will be set?
void QThread::stopServer()
{
m_abort = true; // shall be thread-safe (std::atomic<bool>, etc)
wait(); // It’s optional to use it here
}
void QThread::run()
{
m_server = new QLocalServer();
m_server->Listen("PipeName");
while (!m_abort)
{
if (m_server->waitForNewConnection())
{
/* Most likely you cannot handle the connection
which was closed in another place, therefore сlose (delete)
it after leaving here */
}
}
delete m_server;
}
Please note you can use the standard QThread::requestInterruption and isInterruptionRequested() methods instead of creating own m_abort variable.
From the doc:
This function can be used to make long running tasks cleanly
interruptible. Never checking or acting on the value returned by this
function is safe, however it is advisable do so regularly in long
running functions. Take care not to call it too often, to keep the
overhead low.
So you can write:
void QThread::stopServer()
{
requestInterruption();
wait(); // It’s optional to use it here
}
void QThread::run()
{
m_server = new QLocalServer();
m_server->Listen("PipeName");
while (!isInterruptionRequested())
{
if (m_server->waitForNewConnection(100)) // 100 ms for not to call too often
{
/* Most likely you cannot handle the connection
which was closed in another place, therefore сlose (delete)
it after leaving here */
}
}
delete m_server;
}

Related

ReaderWriterLock blocks when trying to read resource

I am trying to use a ReaderWriterLock for a shared resource between two Tasks.For some reason it starts waiting indefinitely:
class State {
private const int TIMEOUT = 5000;
private ReaderWriterLock lck = new ReaderWriterLock();
private TimeSpan lastIssuedAt;
public TimeSpan LastIssuedAt {
get {
this.lck.AcquireReaderLock(TIMEOUT);
return this.lastIssuedAt;
}
set {
this.lck.AcquireWriterLock(TIMEOUT);
this.lastIssuedAt = value;
}
}
}
When a task tries to get the property LastIssuedAt it just blocks and I do not understand why.
Take a look at the example on MSDN: https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlock?view=netframework-4.8
You forgot to release the lock. A common pattern for doing so is try/finally:
ReaderWriterLock lck = new ReaderWriterLock();
lck.AcquireReaderLock(timeOut);
try
{
// Do what needs to be done under the lock
}
finally
{
// Ensure that the lock is released.
lck.ReleaseReaderLock();
}
Also, check out ReaderWriterLockSlim: https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim?view=netframework-4.8
Which MSDN recommends for new development.

QTimer timeout and QMutex interaction

Let's say we have some basic timer and a slot which is invoked periodically.
SomeObject::SomeObject()
{
QTimer *timer = new QTimer;
connect(timer , SIGNAL(timeout()), this, SLOT(updateState()));
}
void SomeObject::updateState()
{
// some operations leading to update of updatedValue
}
I also have function from same object which forces updates and returns some value.
bool SomeObject::getLatestState()
{
updateState();
return updatedValue;
}
This function may be directly called from different threads. This brings question of thread safety to mind. Simple mutex lock in getLatestState will not help as in some rare cases getLatestState is called from another thread that starts updateState. And at the same time timer's timeout may occur. Can you help me handle this situation properly?
QMutexLocker can be used in such situations
this my exampl
static QMutex mainMutex;
.....
MainController* MainController::s_instance = NULL;
.....
MainController* MainController::getInstance()
{
if(!s_instance){
QMutexLocker lock(&mainMutex);
if(!s_instance){
s_instance = new MainController;
}
}
return s_instance;
}
getInstance() function directly called from different threads.

Java FX - How to terminate a ScheduledService

I wrote a little code to download some files from internet..if user click on cancel button this must be stopped..i use the cancel() method for do it..but it didn't work.
ScheduledService<Object> service = new ScheduledService<Object>() {
protected Task<Object> createTask() {
return new Task<Object>() {
protected Object call() {
if (checkinternet()) {
downloadFiles();
}
return null;
}
};
}
};
service.start();
In buttons action event handler i called cancel method for stop service..
but it wasn't successful..
service.cancel();
How do i do that...
There is no automatic way to cancel a task or service.
From the documentation (https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm):
Cancelling the Task.
There is no reliable way in Java to stop a thread in process. However, the task must stop processing whenever cancel is called on the task. The task is supposed to check periodically during its work whether it was cancelled by using the isCancelled method within the body of the call method.
The example referenced in the above block looks like this:
Task<Integer> task = new Task<Integer>() {
#Override protected Integer call() throws Exception {
int iterations;
for (iterations = 0; iterations < 100000; iterations++) {
if (isCancelled()) {
break;
}
System.out.println("Iteration " + iterations);
}
return iterations;
}
};
So you will have to implement the cancel logic by yourself, unfortunately.

Multiple readers and multiple writers(i mean multiple) synchronization

I am developing a feature that needs a variant of read/write lock that can allow concurrent multiple writers.
Standard read/write lock allows either multiple readers or single writer to run concurrently. I need a variant that can allow multiple readers or multiple writers concurrently. So, it should never allow a reader and a writer concurrently. But, its okay to allow multiple writers at the same time or multiple readers at the same time.
I hope I was clear. I couldn't find any existing algorithm so far. I can think of couple of ways to do this using some queues and etc. But, I dont want to take a risk of doing it myself unless none exists.
Do you guys know of any existing scheme?
Thanks,
The concept you are looking for is a Reentrant lock. You need to be able to try to acquire the lock and not get blocked if the lock is already taken (this is known as reentrant lock). There is a native implementation of a reentrant lock in java so I will illustrate this example in Java. (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html).
Because when using tryLock() you don't get blocked if the lock is not available your writer/reader can proceed. However, you only want to release the lock when you're sure that no one is reading/writing anymore, so you will need to keep the count of readers and writers. You will either need to synchronize this counter or use a native atomicInteger that allows atomic increment/decrement. For this example I used atomic integer.
Class ReadAndWrite {
private ReentrantLock readLock;
private ReentrantLock writeLock;
private AtomicInteger readers;
private AtomicInteger writers;
private File file;
public void write() {
if (!writeLock.isLocked()) {
readLock.tryLock();
writers.incrementAndGet(); // Increment the number of current writers
// ***** Write your stuff *****
writers.decrementAndGet(); // Decrement the number of current writers
if (readLock.isHeldByCurrentThread()) {
while(writers != 0); // Wait until all writers are finished to release the lock
readLock.unlock();
}
} else {
writeLock.lock();
write();
}
}
public void read() {
if (!readLock.isLocked()) {
writeLock.tryLock();
readers.incrementAndGet();
// ***** read your stuff *****
readers.decrementAndGet(); // Decrement the number of current read
if (writeLock.isHeldByCurrentThread()) {
while(readers != 0); // Wait until all writers are finished to release the lock
writeLock.unlock();
}
} else {
readLock.lock();
read();
}
}
What's happening here: First you check if your lock is locked to know if you can perform the action you're going to perform. If it's locked it means you can't read or write so you use lock to put yourself in wait state and re-call the same action when the lock is freed again.
If it's not locked, then you lock the other action (if you're going to read you lock writes and vice-versa) using tryLock. tryLock doesn't block if it's already locked, so several writers can write at the same time and several readers can read at the same time. When the number of threads doing the same thing as you reaches 0 it means that whoever held the lock in the first place can now release it. The only inconvenience with this solution is that the thread that holds the lock will have to stay alive until everyone is finished to be able to release it.
If you are using pthreads, take a look at the synchronization approach in this question.
You could use a similar approach with two variables readerCount and writerCount and a mutex.
In a reader thread you would lock the mutex and wait for writerCount == 0. If this is condition is met, you increment the readerCount by 1 and release the lock. Then you do the reading. When you are done, you lock the mutex again, decrement the readerCount, signal the condition change and release the lock.
The writer thread follows the same logic but waits for the condition readerCount == 0 and increments/decrements writerCount instead.
I did have a solution along the lines of nifs comment. I have posted my solution below. The problem is with fairness policy. Starvation can easily happen. In my approach, one kind of thread is less likely than other. So I am just getting away with giving priority to girls. Ideally we want this to be with some decent fairness policy.
/**
* RestRoomLock:
*
* This lock tries to simulate a gender based access to common rest room.
* It is okay to have multiple boys or multiple girls inside the room. But,
* we can't have boys and girls at the same time inside the room.
*
* This implementation doesn't really have proper fairness policy. For now,
* girls are being treated with priority as long as boys are being gentle,
* boyEntryBeGentle();
*
* #author bmuppana
*/
public class RestRoomLock {
int boysInside;
int girlsInside;
int girlsWaiting;
RestRoomLock() {
boysInside = girlsInside = girlsWaiting = 0;
}
public synchronized void boyEntry() {
while (girlsInside > 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boysInside++;
}
public synchronized void boyEntryBeGentle() {
while (girlsInside + girlsWaiting > 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boysInside++;
}
public synchronized void boyExit() {
boysInside--;
assert boysInside >= 0;
notifyAll();
}
public synchronized void girlEntry() {
girlsWaiting++;
while (boysInside > 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
girlsWaiting--;
girlsInside++;
}
public synchronized void girlExit() {
girlsInside--;
assert girlsInside >= 0;
notifyAll();
}
}

Blocking a Qt application during downloading a short file

I'm writing an application using Qt4.
I need to download a very short text file from a given http address.
The file is short and is needed for my app to be able to continue, so I would like to make sure the download is blocking (or will timeout after a few seconds if the file in not found/not available).
I wanted to use QHttp::get(), but this is a non-blocking method.
I thought I could use a thread : my app would start it, and wait for it to finish. The thread would handle the download and quit when the file is downloaded or after a timeout.
But I cannot make it work :
class JSHttpGetterThread : public QThread
{
Q_OBJECT
public:
JSHttpGetterThread(QObject* pParent = NULL);
~JSHttpGetterThread();
virtual void run()
{
m_pHttp = new QHttp(this);
connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
m_pHttp->setHost("127.0.0.1");
m_pHttp->get("Foo.txt", &m_GetBuffer);
exec();
}
const QString& getDownloadedFileContent() const
{
return m_DownloadedFileContent;
}
private:
QHttp* m_pHttp;
QBuffer m_GetBuffer;
QString m_DownloadedFileContent;
private slots:
void onRequestFinished(int Id, bool Error)
{
m_DownloadedFileContent = "";
m_DownloadedFileContent.append(m_GetBuffer.buffer());
}
};
In the method creating the thread to initiate the download, here is what I'm doing :
JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait();
But that doesn't work and my app keeps waiting. It looks lit the slot 'onRequestFinished' is never called.
Any idea ?
Is there a better way to do what I'm trying to do ?
Instead of using a thread you can just go into a loop which calls processEvents:
while (notFinished) {
qApp->processEvents(QEventLoop::WaitForMore | QEventLoop::ExcludeUserInput);
}
Where notFinished is a flag which can be set from the onRequestFinished slot.
The ExcludeUserInput will ensure that GUI related events are ignored while waiting.
A little late but:
Do not use these wait loops, the correct way is to use the done() signal from QHttp.
The requestFinished signal from what I have seen is just for when your application has finished the request, the data may still be on its way down.
You do not need a new thread, just setup the qhttp:
httpGetFile= new QHttp();
connect(httpGetFile, SIGNAL(done(bool)), this, SLOT(processHttpGetFile(bool)));
Also do not forget to flush the file in processHttpGetFile as it might not all be on the disk.
you have to call QThread::quit() or exit() if you are done - otherwise your thread will run forever...
I chose to implement David's solution, which seemed to be the easiest.
However, I had handle a few more things :
I had to adapt the QEventLoop enum values for Qt4.3.3 (the version I'm using);
I had to track the request Id, to make sure to exit the while loop when the download request is finished, and not when another request is finished;
I added a timeout, to make sure to exit the while loop if there is any problem.
Here is the result as (more or less) pseudo-code :
class BlockingDownloader : public QObject
{
Q_OBJECT
public:
BlockingDownloaderBlockingDownloader()
{
m_pHttp = new QHttp(this);
connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
}
~BlockingDownloader()
{
delete m_pHttp;
}
QString getFileContent()
{
m_pHttp->setHost("www.xxx.com");
m_DownloadId = m_pHttp->get("/myfile.txt", &m_GetBuffer);
QTimer::singleShot(m_TimeOutTime, this, SLOT(onTimeOut()));
while (!m_FileIsDownloaded)
{
qApp->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents);
}
return m_DownloadedFileContent;
}
private slots:
void BlockingDownloader::onRequestFinished(int Id, bool Error)
{
if (Id == m_DownloadId)
{
m_DownloadedFileContent = "";
m_DownloadedFileContent.append(m_GetBuffer.buffer());
m_FileIsDownloaded = true;
}
}
void BlockingDownloader::onTimeOut()
{
m_FileIsDownloaded = true;
}
private:
QHttp* m_pHttp;
bool m_FileIsDownloaded;
QBuffer m_GetBuffer;
QString m_DownloadedFileContent;
int m_DownloadId;
};
I used QNetworkAccsessManager for same necessity. Because this class managing connections RFC base (6 proccess same time) and non-blocking.
http://qt-project.org/doc/qt-4.8/qnetworkaccessmanager.html
How about giving the GUI some amount of time to wait on the thread and then give up.
Something like:
JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait(10000); //give the thread 10 seconds to download
Or...
Why does the GUI thread have to wait for the "downloader thread" at all? When the app fires up create the downloader thread, connect the finished() signal to some other object, start the downloader thread, and return. When the thread has finished, it will signal the other object which can resume your process.

Resources