Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: tools/android/forwarder2/device_listener.h

Issue 19478003: Remove Thread wrapper class in forwarder2. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Digit's comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/android/forwarder2/device_listener.h
diff --git a/tools/android/forwarder2/device_listener.h b/tools/android/forwarder2/device_listener.h
index 44d37aa4ff0b9ce7087061f0228d460414df72b0..2a6982319631ed40a0df87c34127345d6077c34c 100644
--- a/tools/android/forwarder2/device_listener.h
+++ b/tools/android/forwarder2/device_listener.h
@@ -5,76 +5,106 @@
#ifndef TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
#define TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
-#include <pthread.h>
-
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
#include "tools/android/forwarder2/pipe_notifier.h"
#include "tools/android/forwarder2/socket.h"
-#include "tools/android/forwarder2/thread.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
namespace forwarder2 {
class Forwarder;
-class DeviceListener : public Thread {
+// A DeviceListener instance is used in the device_forwarder program to bind to
+// a specific device-side |port| and wait for client connections. When a
+// connection happens, it informs the corresponding HostController instance
+// running on the host, through |host_socket|. Then the class expects a call to
+// its SetAdbDataSocket() method (performed by the device controller) once the
+// host opened a new connection to the device. When this happens, a new internal
+// Forwarder instance is started.
+// Note that instances of this class are owned by the device controller which
+// creates and destroys them on the same thread. In case an internal error
+// happens on the DeviceListener's internal thread, the DeviceListener
+// can also self-delete by executing the user-provided callback on the thread
+// the DeviceListener was created on.
+// Note that the DeviceListener's destructor joins its internal thread (i.e.
+// waits for its completion) which means that the internal thread is guaranteed
+// not to be running anymore once the object is deleted.
+class DeviceListener {
public:
- DeviceListener(scoped_ptr<Socket> adb_control_socket, int port);
- virtual ~DeviceListener();
+ // Callback that is used for self-deletion as a way to let the device
+ // controller perform some additional cleanup work (e.g. removing the device
+ // listener instance from its internal map before deleting it).
+ typedef base::Callback<void (int /* listener port */)> DeleteCallback;
- bool WaitForAdbDataSocket();
+ static scoped_ptr<DeviceListener> Create(
+ scoped_ptr<Socket> host_socket,
+ int port,
+ const DeleteCallback& delete_callback);
- bool SetAdbDataSocket(scoped_ptr<Socket> adb_data_socket);
+ ~DeviceListener();
- bool BindListenerSocket();
+ void Start();
- // |is_alive_| is set only on BindAndListenSocket and written once when Run()
- // terminates. So even in case of a race condition, the worst that could
- // happen is for the main thread to see the listener alive when it isn't. And
- // also, this is not a problem since the main thread checks the liveliness of
- // the listeners in a loop.
- bool is_alive() const { return is_alive_; }
- void ForceExit();
+ void SetAdbDataSocket(scoped_ptr<Socket> adb_data_socket);
int listener_port() const { return listener_port_; }
- protected:
- // Thread:
- virtual void Run() OVERRIDE;
-
private:
- void RunInternal();
-
- // Must be called after successfully acquired mutex.
- void SetMustExitLocked();
-
- // The listener socket for sending control commands.
- scoped_ptr<Socket> adb_control_socket_;
-
+ DeviceListener(scoped_ptr<PipeNotifier> pipe_notifier,
+ scoped_ptr<Socket> listener_socket,
+ scoped_ptr<Socket> host_socket,
+ int port,
+ const DeleteCallback& delete_callback);
+
+ // Pushes an AcceptClientOnInternalThread() task to the internal thread's
+ // message queue in order to wait for a new client soon.
+ void AcceptNextClientSoon();
+
+ void AcceptClientOnInternalThread();
+
+ void OnAdbDataSocketReceivedOnInternalThread(
+ scoped_ptr<Socket> adb_data_socket);
+
+ void SelfDelete();
+
+ // Note that this can be called after the DeviceListener instance gets deleted
+ // which is why this method is static.
+ static void SelfDeleteOnDeletionTaskRunner(
+ const DeleteCallback& delete_callback,
+ int listener_port);
+
+ // Used for the listener thread to be notified on destruction. We have one
+ // notifier per Listener thread since each Listener thread may be requested to
+ // exit for different reasons independently from each other and independent
+ // from the main program, ex. when the host requests to forward/listen the
+ // same port again. Both the |host_socket_| and |listener_socket_|
+ // must share the same receiver file descriptor from |exit_notifier_| and it
+ // is set in the constructor.
+ const scoped_ptr<PipeNotifier> exit_notifier_;
// The local device listener socket for accepting connections from the local
// port (listener_port_).
- Socket listener_socket_;
-
+ const scoped_ptr<Socket> listener_socket_;
+ // The listener socket for sending control commands.
+ const scoped_ptr<Socket> host_socket_;
+ scoped_ptr<Socket> device_data_socket_;
// This is the adb connection to transport the actual data, used for creating
// the forwarder. Ownership transferred to the Forwarder.
scoped_ptr<Socket> adb_data_socket_;
-
- int listener_port_;
- pthread_mutex_t adb_data_socket_mutex_;
- pthread_cond_t adb_data_socket_cond_;
- bool is_alive_;
- bool must_exit_;
-
- // Used for the listener thread to be notified from ForceExit() which is
- // called from the main thread. We have one notifier per Listener thread since
- // each Listener thread may be requested to exit for different reasons
- // independently from each other and independent from the main program,
- // ex. when the host requests to forward/listen the same port again. Both the
- // |adb_control_socket_| and |listener_socket_| must share the same receiver
- // file descriptor from |exit_notifier_| and it is set in the constructor.
- PipeNotifier exit_notifier_;
+ const int listener_port_;
+ const DeleteCallback delete_callback_;
+ // Task runner used for deletion set at construction time (i.e. the object is
+ // deleted on the same thread it is created on).
+ scoped_refptr<base::SingleThreadTaskRunner> deletion_task_runner_;
+ base::Thread thread_;
DISALLOW_COPY_AND_ASSIGN(DeviceListener);
};

Powered by Google App Engine
This is Rietveld 408576698