views:

219

answers:

4

There is ConnectionManager which waits for incoming connections. For each incoming connection it creates a Connection instance which handles the inbound and outbound traffic on this connection. Each Connection has a Watchdog which handles "bad connection" conditions and calls registered "Listerners". One "Listener" is the ConnectionManager which closes the connection and deletes the Connection instance which in turn deletes the corresponding Watchdog.

Wait. A. Minute.

The Watchdog calls the ConnectionManager which deletes the Connection which deletes the Watchdog? The Watchdog chases its own tail.

I am completly blocked. How do I resolve this?


Solution: I will make the Listener thingy asynchronous, altough I don't know yet how to do that without too much pain. The Watchdog doesn't know about the ConnectionManager. It is fairly generic. Also the Win32-Thread-API doesn't have something like "join", so I might need to roll my own with GetExitCodeThread() and STILL_ACTIVE...

Thanks, guys.

+3  A: 

Messaging.

Instead of having the Watchdog call a method of the ConnectionManager, post a message to a queue in the connection manager. This queue needs to be thread safe. When the ConnectionManager processes the queue in its thread, it will be safe to wait for the Connection thread to end.

Watchdog          Queue               ConnectionManager
   |                |                        |
Kill Connection---->|                        |
   |                |<-------------------Get Message
  ---               |                        |
                    |-------------------->Process Message
                    |                        |
                    |                     Kill Connection

Skizz

Skizz
+2  A: 

If each of these objects is running in its own thread there is no problem.

The Watchdog notifies the ConnectionManager and returns.
At this point the Watchdog thread can just exit.

When the ConnectionManager notices the watchdog event it kills the Connection thread.

Martin York
+2  A: 

If the watchdog is running in a different thread, then the problem isn't too bad - the watchdog signals the ConnectionManager to delete with a asynchronous message, then exits it's own thread.

Mean-while, the ConnectionManager thread gets the delete message, and starts deleting the watchdog.

To avoid race-conditions the watchdog destructor should join the watchdog thread, and cleanup the thread. (Probably also signal the watchdog thread, or assert() something about the watchdog thread being ready to exit).

Douglas Leeder
A: 

If you're carefull there isn't a problem.

  1. ConnectionInstance::a_method() calls Watchdog::a_method() calls ConnectionManager::a_method

  2. ConnectionManager::a_method() deletes ConnectionInstance deletes Watchdog

  3. ConnectionManager::a_method() returns to Watchdog::a_method() returns to ConnectionInstance::a_method(). As long as the return path doesn't access any members it's just a return from a function. The code is still there by the standard, so you can safely return.

This requires careful coding and maintaining, but it's not a dirty hack it may seem.

Asynchronous protocol will require same amount of thinking. It's not just that you'll need to avoid racing between Watchdog requesting delete in a ConnectionManager::queue and ConnectionManager doing something with the queue at the same time. The problem is deeper: there's a period of time when ConnectionInstance is not functional - it has requested to be deleted - but not still deleted. What it it doing? A code can not stay still. If there's a safe way out for the not defunct ConnectionInstance, you can as well roll back the stack yourself without creating extra asynchronous protocols.

Watchdog throwing an exception might be an easier way to deal with ConnectionInstance, if they are in the same thread.

n-alexander