Index: tools/android/forwarder2/host_forwarder_main.cc |
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc |
index e38d8cbda5dc167a8fde512877f35b9531fcf4cb..1071aa7dd42a82d7b0db8b92695c079c8d374ca7 100644 |
--- a/tools/android/forwarder2/host_forwarder_main.cc |
+++ b/tools/android/forwarder2/host_forwarder_main.cc |
@@ -16,6 +16,7 @@ |
#include <vector> |
#include "base/at_exit.h" |
+#include "base/basictypes.h" |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/compiler_specific.h" |
@@ -25,6 +26,7 @@ |
#include "base/logging.h" |
#include "base/memory/linked_ptr.h" |
#include "base/memory/scoped_vector.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/pickle.h" |
#include "base/posix/eintr_wrapper.h" |
#include "base/safe_strerror_posix.h" |
@@ -80,9 +82,24 @@ void KillHandler(int signal_number) { |
exit(1); |
} |
+// Manages HostController instances. There is one HostController instance for |
+// each connection being forwarded. Note that forwarding can happen with many |
+// devices (identified with a serial id). |
class HostControllersManager { |
public: |
- HostControllersManager() : has_failed_(false) {} |
+ HostControllersManager() |
+ : weak_ptr_factory_(this), |
+ controllers_(new HostControllerMap()), |
+ has_failed_(false) { |
+ } |
+ |
+ ~HostControllersManager() { |
+ if (!thread_.get()) |
+ return; |
+ // Delete the controllers on the thread they were created on. |
+ thread_->message_loop_proxy()->DeleteSoon( |
+ FROM_HERE, controllers_.release()); |
+ } |
void HandleRequest(const std::string& device_serial, |
int device_port, |
@@ -117,25 +134,24 @@ class HostControllersManager { |
} |
// Invoked when a HostController instance reports an error (e.g. due to a |
- // device connectivity issue). |
- void DeleteHostController(HostController* host_controller) { |
- if (!thread_->message_loop_proxy()->RunsTasksOnCurrentThread()) { |
- // This can be invoked from the host controller internal thread. |
- thread_->message_loop_proxy()->PostTask( |
- FROM_HERE, |
- base::Bind( |
- &HostControllersManager::DeleteHostControllerOnInternalThread, |
- base::Unretained(this), host_controller)); |
+ // device connectivity issue). Note that this could be called after the |
+ // controller manager was destroyed which is why a weak pointer is used. |
+ static void DeleteHostController( |
+ const base::WeakPtr<HostControllersManager>& manager_ptr, |
+ scoped_ptr<HostController> host_controller) { |
+ HostController* const controller = host_controller.release(); |
+ HostControllersManager* const manager = manager_ptr.get(); |
+ if (!manager) { |
+ // Note that |controller| is not leaked in this case since the host |
+ // controllers manager owns the controllers. If the manager was deleted |
+ // then all the controllers (including |controller|) were also deleted. |
return; |
} |
- DeleteHostControllerOnInternalThread(host_controller); |
- } |
- |
- void DeleteHostControllerOnInternalThread(HostController* host_controller) { |
- // Note that this will delete |host_controller| which is owned by the map. |
- controllers_.erase( |
- MakeHostControllerMapKey(host_controller->adb_port(), |
- host_controller->device_port())); |
+ DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); |
+ // Note that this will delete |controller| which is owned by the map. |
+ manager->controllers_->erase( |
+ MakeHostControllerMapKey(controller->adb_port(), |
+ controller->device_port())); |
} |
void HandleRequestOnInternalThread(const std::string& device_serial, |
@@ -154,7 +170,7 @@ class HostControllersManager { |
// Remove the previously created host controller. |
const std::string controller_key = MakeHostControllerMapKey( |
adb_port, -device_port); |
- const HostControllerMap::size_type removed_elements = controllers_.erase( |
+ const HostControllerMap::size_type removed_elements = controllers_->erase( |
controller_key); |
SendMessage( |
!removed_elements ? "ERROR: could not unmap port" : "OK", |
@@ -169,7 +185,7 @@ class HostControllersManager { |
if (!use_dynamic_port_allocation) { |
const std::string controller_key = MakeHostControllerMapKey( |
adb_port, device_port); |
- if (controllers_.find(controller_key) != controllers_.end()) { |
+ if (controllers_->find(controller_key) != controllers_->end()) { |
LOG(INFO) << "Already forwarding device port " << device_port |
<< " to host port " << host_port; |
SendMessage(base::StringPrintf("%d:%d", device_port, host_port), |
@@ -179,11 +195,11 @@ class HostControllersManager { |
} |
// Create a new host controller. |
scoped_ptr<HostController> host_controller( |
- new HostController( |
- device_port, "127.0.0.1", host_port, adb_port, GetExitNotifierFD(), |
+ HostController::Create( |
+ device_port, host_port, adb_port, GetExitNotifierFD(), |
base::Bind(&HostControllersManager::DeleteHostController, |
- base::Unretained(this)))); |
- if (!host_controller->Connect()) { |
+ weak_ptr_factory_.GetWeakPtr()))); |
+ if (!host_controller.get()) { |
has_failed_ = true; |
SendMessage("ERROR: Connection to device failed.", client_socket.get()); |
return; |
@@ -196,7 +212,7 @@ class HostControllersManager { |
if (!SendMessage(msg, client_socket.get())) |
return; |
host_controller->Start(); |
- controllers_.insert( |
+ controllers_->insert( |
std::make_pair(MakeHostControllerMapKey(adb_port, device_port), |
linked_ptr<HostController>(host_controller.release()))); |
} |
@@ -232,8 +248,9 @@ class HostControllersManager { |
return result; |
} |
+ base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_; |
base::hash_map<std::string, int> device_serial_to_adb_port_map_; |
- HostControllerMap controllers_; |
+ scoped_ptr<HostControllerMap> controllers_; |
bool has_failed_; |
scoped_ptr<base::AtExitManager> at_exit_manager_; // Needed by base::Thread. |
scoped_ptr<base::Thread> thread_; |