0

So I have an application which is a server that opens several threads which will be used for database queries. In my receive function, I tested the output for my query which I built and it looks fine when I cout the ostringstream, so I add it to a vector. I then cout the vector and it also looks fine. This is all done within a mutex lock, so then I unlock the mutex. My database threads are in a while loop which checks to see if my vector.size() > 0.

The problem I am having is that my loop never runs, because it never sees the vector > 0(Which it should be because I was able to cout the vector.begin() and it worked fine. Could anyone take a look at the code I have and tell me if there are any problems that might be causing this issue.

#Header
class CNetworkService : public Service
{
   public:
CNetworkService(void);
~CNetworkService(void);
std::ostringstream query;
string  record;
std::vector<string> queue;
string IP;
unsigned int Port;
void DBWork();
bool SaveLog(string insert);
   protected:
virtual void handle(LogicalConnection* pClient, IncomingPacket* pRequest);
};

#Source File
//In my receive handler
    mtx.lock();
query << var1 << var2;

queue.push_back(query.str());
mtx.unlock();
query.clear();



//This is the function that the database threads are looping in
void CNetworkService::DBWork()
{


while(true)
{
mtx.lock();
while(queue.size() > 0)
{
    printf("Adding new record \n");
    SaveLog(queue.front());
    queue.erase(queue.begin());

}
mtx.unlock();
    }
    }

  //The code in the main thread which launches each thread. StartDBThread does some reporting stuff and then lauches the DBWork function, and I can see that DBWork is getting called. In the original attempt I was trying to launch 4 threads, but for now I have scaled it back to 1 thread in order to test and get a working solution.
  std::thread threads[1];
  // spawn 1 threads:
  for (int i=0; i<1; ++i)
  threads[i] = std::thread(StartDBThread, i+1);

  for (auto& th : threads) th.join();
Uwop
  • 89
  • 1
  • 2
  • 7
  • The normal way to use thread safe queues is by using condition variables. See following example: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html – stefaanv Apr 22 '14 at 14:14
  • 1
    If you really want a queue, why not use [`std::queue`](http://en.cppreference.com/w/cpp/container/queue)? – Some programmer dude Apr 22 '14 at 14:18
  • Thanks, I didn't know about queue's, but unfortunately this question is not about vector's vs queue's and my problem still remains. – Uwop Apr 22 '14 at 14:59

1 Answers1

0

One of the possible problems I could think of is that the mutex is being acquired somewhere else in your code and CNetworkService::DBWork() never got the lock.

This might not be the cause of the problem. But you can prevent it by having the mtx variable a private field of CNetworkService since it's used to synchronize the queue and you don't want it to be used elsewhere.

I suggest you test by printing something in between mtx.lock() and while(queue.size() > 0) to see if the lock is ever being acquired.

P.S. vector::erase is very expensive.

Yifu Wang
  • 313
  • 2
  • 9
  • I'm able to get the lock in the other thread, the problem is the other thread never see's the size of my vector going up. I just tried outputting the first value of my vector using cout << queue.front() << endl; and I'm not able to within the DBWork thread, within the mutex lock. – Uwop Apr 22 '14 at 16:26
  • Also thanks for the tip about vector erase, I changed it to pop_back() – Uwop Apr 22 '14 at 16:31
  • @AES256 You want to make sure if the thread calling `CNetworkService::DBWork()` doesn't see the size going up, or the `queue.size() > 0` condition never gets executed at all. It sounds like the second case, it probably means that the `mtx` is being acquired by some other thread and without being released. Also, have you joined the thread that's calling `CNetworkService::DBWork()` in your main thread? It would be helpful if you paste the code. – Yifu Wang Apr 22 '14 at 17:36
  • Here is the thread creation code. std::thread threads[1]; // spawn 1 threads: for (int i=0; i<1; ++i) threads[i] = std::thread(StartDBThread, i+1); for (auto& th : threads) th.join(); – Uwop Apr 23 '14 at 14:58
  • I also added it to the main post at the bottom of the code section. – Uwop Apr 23 '14 at 15:05