🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.oodesign
Article #48

Problem with accessing Queue from worker thread

#48
From: Daniel Stevenson
Date: Tue, 22 Mar 2005 00:48
364 lines
11007 bytes
I've created a thread safe queue using the STL queue, in the main thread I
push objects onto the queue and within my thread I interrogate the queue to
see if the size increases and if so I then pop the object off and perform
something.

My problem seems to be simple in that I can't seem to access the same queue
pointer from within my thread as I do within my main thread.

In my main thread as I pop objects onto the queue, I can see the size
increase but whenever I interrogate the queue from the worker thread it
always returns zero....and I'm sure I'm doing something stupidly simple but
i can't seem to see what that is...can someone point out my stupidity.

I have summarized by code below...

...LogQueueSource.h file...
//--------------------------------------------------------------------------
-

#ifndef TLogQueueSourceH
#define TLogQueueSourceH
//--------------------------------------------------------------------------
-
#include <queue>
//--------------------------------------------------------------------------
-
//--------------------------------------------------------------------------
-
typedef struct LogStruct
{
  long StatusType;
  AnsiString Origin;
  long Level;
  AnsiString Description;
  TDateTime DateStamp;
  TDateTime TimeStamp;
  AnsiString CallNumber;
  AnsiString DisplayMessage;
  long Priority;
  long PagingID;
  AnsiString Subject;
  AnsiString Body;
  long IndicationCode;
  bool BreakThrough;
  long ConfirmationType;
  bool IsErase;
  long TimeToLive;
  bool AllowRemoteDelete;
} LogInfo;
//--------------------------------------------------------------------------
-
class CriticalSection
{
private:
  CRITICAL_SECTION m_cs;
public:
  CriticalSection()
  {
    ::InitializeCriticalSection(&m_cs);
  }
  CriticalSection(const CriticalSection& rhs)
  {
    // ignore rhs
    ::InitializeCriticalSection(&m_cs);
  }
  ~CriticalSection()
  {
    ::DeleteCriticalSection(&m_cs);
  }
  CriticalSection& operator=(const CriticalSection& rhs)
  {
    // ignore rhs & do nothing
    return *this;
  }
  void Enter()
  {
    ::EnterCriticalSection(&m_cs);
  }
  void Leave()
  {
    ::LeaveCriticalSection(&m_cs);
  }
};
//--------------------------------------------------------------------------
-
class CriticalSectionLock
{
private:
  CriticalSection& m_cs;

  // unimplemented
  CriticalSectionLock& operator=(const CriticalSectionLock&);
  CriticalSectionLock(const CriticalSectionLock&);
public:
  CriticalSectionLock(CriticalSection& cs)
      : m_cs(cs)
  {
    m_cs.Enter();
  }

  ~CriticalSectionLock()
  {
    m_cs.Leave();
  }
};
//--------------------------------------------------------------------------
-
template <class T>
class TLogQueue
{
private:
 std::queue<T>    m_q;
 CriticalSection  m_cs;

public:
  typedef T value_type;
  // .. other typedefs as needed

  void push(const value_type& v)
  {
    CriticalSectionLock lock(m_cs);
    m_q.push(v);
  }

  void pop()
  {
    CriticalSectionLock lock(m_cs);
    m_q.pop();
  }

  unsigned int size()
  {
    CriticalSectionLock lock(m_cs);
    unsigned int size = m_q.size();

    return size;
  }

  const value_type& front() const
  {
    return m_q.front();
  }

  const value_type& top() const
  {
    // CriticalSectionLock lock(m_cs);
    return m_q.top();
  }
};
//--------------------------------------------------------------------------
-
#endif

I don't think there is anything wrong with the above declaration, I included
this to reduce the number of questions in this area.
I think the problem is in how I've declared my queue but I'm having a brain
freeze and can't think straight to work out my problem as seen below.


....LoggingServiceSource.h...
//--------------------------------------------------------------------------
-
#ifndef LoggingServiceSourceH
#define LoggingServiceSourceH
//--------------------------------------------------------------------------
-
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <SvcMgr.hpp>
#include <vcl.h>
#include "thdLoggingSource.h"
#include <OleServer.hpp>
#include <queue>
using namespace std;
//--------------------------------------------------------------------------
-
TLogQueue<LogStruct> LogQueue;            //declaring my queue
//--------------------------------------------------------------------------
-
class TLoggingService : public TService
{
__published:    // IDE-managed Components
  TatSystemStatus *atSystemStatus;
  TatPagingSubscription *atPagingSubscription;
  void __fastcall atSystemStatusSystemStatus(TObject *Sender,
          atSystemStatusType StatusType, BSTR Origin,
          atSystemStatusLevel Level, BSTR Description);
  void __fastcall atPagingSubscriptionPaging(TObject *Sender,
          BSTR CallNumber, BSTR DisplayMessage, long Priority,
          PagingInfoStruct *AdditionalInfo);
private:        // User declarations
  TLoggingThread *LoggingThread;
  String ConnectionStatus;

  void __fastcall UpdateServiceDescription(TService *Sender);
  void __fastcall CreateWorkerThread();
  void __fastcall CheckSystemStatus();
public:         // User declarations
 __fastcall TLoggingService(TComponent* Owner);
 TServiceController __fastcall GetServiceController(void);

 friend void __stdcall ServiceController(unsigned CtrlCode);
};
//--------------------------------------------------------------------------
-
extern PACKAGE TLoggingService *LoggingService;
//--------------------------------------------------------------------------
-
#endif



...LoggingServiceSource.cpp....
//--------------------------------------------------------------------------
-
#include "LoggingServiceSource.h"
#include <deque>
#include "LogQueueSource.h"
//--------------------------------------------------------------------------
-
#pragma package(smart_init)
#pragma resource "*.dfm"


TLoggingService *LoggingService;
//--------------------------------------------------------------------------
-
__fastcall TLoggingService::TLoggingService(TComponent* Owner)
 : TService(Owner)
{
  CreateWorkerThread();
  CheckSystemStatus();
}
//--------------------------------------------------------------------------
-
TServiceController __fastcall TLoggingService::GetServiceController(void)
{
 return (TServiceController) ServiceController;
}
//--------------------------------------------------------------------------
-
void __stdcall ServiceController(unsigned CtrlCode)
{
 LoggingService->Controller(CtrlCode);
}
//--------------------------------------------------------------------------
-
void __fastcall TLoggingService::atSystemStatusSystemStatus(TObject *Sender,
      atSystemStatusType StatusType, BSTR Origin,
      atSystemStatusLevel Level, BSTR Description)
{
  //log all this information in the queue
  LogInfo NewLog;
  NewLog.StatusType = StatusType;
  NewLog.Origin = Origin;
  NewLog.Level = Level;
  NewLog.Description = Description;
  NewLog.DateStamp = TDateTime::CurrentDate();
  NewLog.TimeStamp = TDateTime::CurrentTime();

  LogQueue.push(NewLog);
  unsigned int size = LogQueue.size();            //this value is
incremented correctly after each push
}
//--------------------------------------------------------------------------
-
void __fastcall TLoggingService::CreateWorkerThread()
{
  LoggingThread = new TLoggingThread(false);
  LoggingThread->FreeOnTerminate = true;
  LoggingThread->Resume();
}
//--------------------------------------------------------------------------
-
void __fastcall TLoggingService::CheckSystemStatus()
{
  atSystemStatus->QueryConnectionStatus();
}
//--------------------------------------------------------------------------
-



all of the above seems to work fine (please ignore the fact that I will have
problems with my struct definition and what is actually stored on the queue,
I am more interested in that fact that when something is stored on the queue
I can see that from my worker thread as seem below...


...LoggingSource.h...
//--------------------------------------------------------------------------
-

#ifndef thdLoggingSourceH
#define thdLoggingSourceH
//--------------------------------------------------------------------------
-
#include <Classes.hpp>
#include "LogQueueSource.h"
//--------------------------------------------------------------------------
-
class TLoggingThread : public TThread
{
private:
  void __fastcall ProcessQueueData();
protected:
  void __fastcall Execute();
public:
  __fastcall TLoggingThread(bool CreateSuspended);
};
//--------------------------------------------------------------------------
-
#endif


...LoggingSource.cpp...
//--------------------------------------------------------------------------
-

#include <vcl.h>
#pragma hdrstop

#include "thdLoggingSource.h"
#include "frmLoggingServiceSource.h"
#include "LogQueueSource.h"
#pragma package(smart_init)
//--------------------------------------------------------------------------
-
__fastcall TLoggingThread::TLoggingThread(bool CreateSuspended)
  : TThread(CreateSuspended)
{
}
//--------------------------------------------------------------------------
-
void __fastcall TLoggingThread::Execute()
{
  while (!Terminated)
  {
    unsigned int size = LogQueue.size();            //this returns zero no
matter how big the queue is in the main thread

    if (size > 0)
    {
      int i = 0;
      i = i;
      //ProcessQueueData();
    }
    else
    {
      Sleep(5000);
    }
  }
}
//--------------------------------------------------------------------------
-
void __fastcall TLoggingThread::ProcessQueueData()
{
  LogInfo NewLog = LogQueue.front();
  LogQueue.pop();

    ///do something here
}
//--------------------------------------------------------------------------
-
Technical Details
Message-ID: <423f6b65@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!news.glorb.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newshosting.com!nx02.iad01.newshosting.com!news-out.nntp.be!propagator2-sterling.newsfeeds.com!news-in.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 10db1e,62ae9303d665b63f,start
X-Google-Attributes: gid10db1e,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Daniel Stevenson" <d.stevenson@ocreage.com.au>
Newsgroups: borland.public.cppbuilder.oodesign
Subject: Problem with accessing Queue from worker thread
Date: Tue, 22 Mar 2005 11:48:35 +1100
Lines: 370
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
NNTP-Posting-Host: 202.174.233.53
Message-ID: <423f6b65@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1111452517 202.174.233.53 (21 Mar 2005 16:48:37 -0800)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!news.glorb.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newshosting.com!nx02.iad01.newshosting.com!news-out.nntp.be!propagator2-sterling.newsfeeds.com!news-in.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mail