title: Are C++ Pointers to Non-Reentrant Qt Data Types Reentrant and Safe to Pass from Main GUI Thread to a Worker Thread?
body: <p>Hi I have a c++ object (BackupJob) that stores data for backup jobs to be passed between a main GUI thread and a worker thread using Qt signals and slots. It contains lots of reentrant Qt data types like QVectors QStringLists QDateTimes etc which I know are safe to pass between threads... I am considering storing pointers to a QThread, a QObject, and a Win API HANDLE in the backupjob objects. QThread is not reentrant.</p>
  
  <p>Is this safe to do as long as the pointers are passed by value via signals and slots in the backupjob object and the underlying data pointed to is not modified? Are pointers reentrant and can be passed between threads even if the underlying data type pointed to is not reentrant?
  I am using the definition of reentrancy as <a href="https://doc.qt.io/archives/qt-4.8/threads-reentrancy.html" rel="nofollow noreferrer">here</a>.</p>
  
  <p>The situation might be further complicated by the fact that the thread pointed to in the backupjob object is separate from the main GUI thread and worker thread, monitoring directory changes on its own. The watchDirObject object lives in dirMonThread, with separate dir watching threads for each backupjob. The worker thread performs on demand backups while the dir watching threads detect directory changes in real time. I assume the same underlying principle remains the only relevant thing to consider, whether those pointers are safe to pass between threads.</p>
  
  <p>Thanks!</p>
  
  <p>Here is some code:</p>
  
  <pre><code>//executed in main thread
  workerThread = new QThread(this);
  workerThread-&gt;start();
  worker = new Worker;
  worker-&gt;moveToThread(workerThread);
  connect(this, SIGNAL(backup(QList&lt;BackupJob&gt;,QList&lt;BackupJob&gt;)), worker, SLOT(backup(QList&lt;BackupJob&gt;,QList&lt;BackupJob&gt;)));
  
  class BackupJob
  {
  ...
  QList&lt;std::pair&lt;BBFileInfo, BBFileInfo&gt; &gt; fileList;
  QMap&lt;QString,qint64&gt; requiredSize, peakSize;
  ...
  QThread *dirMonThread;
  //WatchDirectory QObject moved to dirMonThread
  WatchDirectory *watchDirObject;
  HANDLE dirMonThreadObjectHandle;
  }
  
  //executed in main thread to set up directory watching thread
  void Replicator::setupJobContinuousThread(BackupJob &amp;job)
  {
  if (!CreateEvent(NULL,TRUE,FALSE,job.getName().toStdWString().c_str()))
      win32Error(TEXT("CreateEvent"));
  job.setupContinuousThread(this);
  connect(job.getContinuousThread(),&amp;QThread::finished,job.getContinuousObject(),&amp;QObject::deleteLater);
  connect(job.getContinuousObject(),&amp;WatchDirectory::sendRealTimeOperationJob,this,&amp;Replicator::commitRealTimeOperations);
  //connect(replicator,&amp;Replicator::dirMon,job.getContinuousObject(),&amp;WatchDirectory::startWatch);
  QMetaObject::invokeMethod(job.getContinuousObject(),"startWatch",Qt::QueuedConnection);
  }
  
  void BackupJob::setupContinuousThread(Replicator *replicator)
  {
  dirMonThread = new QThread(replicator);
  dirMonThread-&gt;start();
  watchDirObject = new WatchDirectory;
  watchDirObject-&gt;moveToThread(dirMonThread);
  }
  </code></pre>