0

Wow, I wish I'd known about this page https://github.com/zaphoyd/websocketpp/blob/experimental/examples/broadcast_server/broadcast_server.cpp written by my c++ hero https://stackoverflow.com/users/1047661/zaphoyd before I started my c++ websocket adventure. Tons of lessons there.

If I'm reading it correctly (that's a stretch lol), it looks like connections and message sends & receipts are all handled in a single thread (can't wait til he "multi-threads" that or whatever it's called since he says in this basic example http://www.zaphoyd.com/websocketpp/manual/common-patterns/server-initiated-messages that WebSocket++ handlers block core networking functions. While this program is running its send loop in on_message, no new connections are being processed and no new messages are being received.) and a separate thread boost::thread(bind(&broadcast_server::process_messages,&server)); is set up to actually process the messages while the primary websocket++ thread simply adds to the queue the necessary information.

Please clear up my lack of knowledge: will the .push() fail if it happens at the same time as this section of code in the link

while(m_actions.empty()) {
    m_action_cond.wait(lock);
}

action a = m_actions.front();
m_actions.pop();

lock.unlock();

or does the .push() simply wait for the lock to be released?

Community
  • 1
  • 1
  • 1
    `std::queue` is not multi-threading aware. You can't lock it, and it doesn't fail or wait during contention. (Though contention involving a write will no doubt result in undefined behavior causing sporadic crashes.) – Cory Nelson Mar 10 '13 at 05:47
  • @CoryNelson the code the OP linked to is coded correctly to acquire the lock before calling `push` – Stephen Lin Mar 10 '13 at 05:58
  • 2
    Indeed. OP worded his question in a way that indicates a misunderstanding of `std::queue`'s involvement in locking. – Cory Nelson Mar 10 '13 at 06:16
  • 1
    yes, I know, but he asked about what was happening in that particular example, so it's more helpful to explain what's happening there in addition to correcting that misunderstanding...anyway, i already answered, so no worries – Stephen Lin Mar 10 '13 at 06:23
  • @CoryNelson +1 for bottom line: sporadic crashes –  May 24 '13 at 01:29

1 Answers1

1

std::queue<T> doesn't know anything about threading on its own; however, in the code linked, all calls to push are wrapped like the following:

    boost::unique_lock<boost::mutex> lock(m_action_lock);
    //std::cout << "on_open" << std::endl;
    m_actions.push(action(SUBSCRIBE,hdl));
    lock.unlock();
    m_action_cond.notify_one();

The constructor of the lock object above internally calls m_action_lock.lock() which blocks until the lock is released.

Note that m_action_cond.wait(lock), in the code you pasted in your question, unlocks the lock while waiting for the condition, and acquires the lock again after it has been woken up (either due to a signal from another thread, or possibly spuriously), so it doesn't prevent the producer (the one doing the push) thread from acquiring the lock while it's waiting: it's only between waking up and the call to lock.unlock() that blocking occurs.

Community
  • 1
  • 1
Stephen Lin
  • 5,470
  • 26
  • 48
  • 1
    it doesn't have anything to do with the `push`; if you call `push` without acquiring the lock first it will execute but will have undefined effects, because of the data race: the constructor of `boost::unique_lock` will block, though, until the lock can be acquired. – Stephen Lin Mar 10 '13 at 06:01
  • 1
    (that comment was aimed at the comment you deleted...I'll leave it in case it's helpful) – Stephen Lin Mar 10 '13 at 06:02