Index: athena/system/device_socket_listener.cc |
diff --git a/athena/system/device_socket_listener.cc b/athena/system/device_socket_listener.cc |
index e041e44c5413d38bfdedcc53eb3781a8c7668e27..032b3f503e76bfee88b3f03e30e46ec7d5401b20 100644 |
--- a/athena/system/device_socket_listener.cc |
+++ b/athena/system/device_socket_listener.cc |
@@ -12,7 +12,6 @@ |
#include "base/bind.h" |
#include "base/files/file_path.h" |
-#include "base/memory/singleton.h" |
#include "base/message_loop/message_loop.h" |
#include "base/observer_list.h" |
#include "base/stl_util.h" |
@@ -55,17 +54,22 @@ DeviceSocketManager* device_socket_manager_instance_ = NULL; |
// A singleton instance for managing all connections to sockets. |
class DeviceSocketManager { |
public: |
- static void Create(scoped_refptr<base::TaskRunner> io_task_runner) { |
- device_socket_manager_instance_ = |
- new DeviceSocketManager(io_task_runner); |
+ static void Create(scoped_refptr<base::TaskRunner> file_task_runner) { |
+ device_socket_manager_instance_ = new DeviceSocketManager(file_task_runner); |
} |
static void Shutdown() { |
CHECK(device_socket_manager_instance_); |
- delete device_socket_manager_instance_; |
+ device_socket_manager_instance_->ScheduleDelete(); |
+ // Once scheduled to be deleted, no-one should be |
+ // able to access it. |
device_socket_manager_instance_ = NULL; |
} |
+ static DeviceSocketManager* GetInstanceUnsafe() { |
+ return device_socket_manager_instance_; |
+ } |
+ |
static DeviceSocketManager* GetInstance() { |
CHECK(device_socket_manager_instance_); |
return device_socket_manager_instance_; |
@@ -94,8 +98,6 @@ class DeviceSocketManager { |
void OnEOF(const std::string& socket_path); |
private: |
- friend struct DefaultSingletonTraits<DeviceSocketManager>; |
- |
struct SocketData { |
SocketData() |
: fd(-1) { |
@@ -107,26 +109,29 @@ class DeviceSocketManager { |
scoped_ptr<DeviceSocketReader> watcher; |
}; |
- DeviceSocketManager(scoped_refptr<base::TaskRunner> io_task_runner) |
- : io_task_runner_(io_task_runner) { |
- } |
+ static void DeleteOnFILE(DeviceSocketManager* manager) { delete manager; } |
+ |
+ DeviceSocketManager(scoped_refptr<base::TaskRunner> file_task_runner) |
+ : file_task_runner_(file_task_runner) {} |
~DeviceSocketManager() { |
STLDeleteContainerPairSecondPointers(socket_data_.begin(), |
socket_data_.end()); |
} |
- void StartListeningOnIO(const std::string& socket_path, |
- size_t data_size, |
- DeviceSocketListener* listener); |
+ void ScheduleDelete(); |
+ |
+ void StartListeningOnFILE(const std::string& socket_path, |
+ size_t data_size, |
+ DeviceSocketListener* listener); |
- void StopListeningOnIO(const std::string& socket_path, |
- DeviceSocketListener* listener); |
+ void StopListeningOnFILE(const std::string& socket_path, |
+ DeviceSocketListener* listener); |
void CloseSocket(const std::string& socket_path); |
std::map<std::string, SocketData*> socket_data_; |
- scoped_refptr<base::TaskRunner> io_task_runner_; |
+ scoped_refptr<base::TaskRunner> file_task_runner_; |
DISALLOW_COPY_AND_ASSIGN(DeviceSocketManager); |
}; |
@@ -162,23 +167,31 @@ void DeviceSocketReader::OnFileCanWriteWithoutBlocking(int fd) { |
void DeviceSocketManager::StartListening(const std::string& socket_path, |
size_t data_size, |
DeviceSocketListener* listener) { |
- io_task_runner_->PostTask(FROM_HERE, |
- base::Bind(&DeviceSocketManager::StartListeningOnIO, |
- base::Unretained(this), socket_path, data_size, listener)); |
+ file_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&DeviceSocketManager::StartListeningOnFILE, |
+ base::Unretained(this), |
+ socket_path, |
+ data_size, |
+ listener)); |
} |
void DeviceSocketManager::StopListening(const std::string& socket_path, |
DeviceSocketListener* listener) { |
- io_task_runner_->PostTask(FROM_HERE, |
- base::Bind(&DeviceSocketManager::StopListeningOnIO, |
- base::Unretained(this), socket_path, listener)); |
+ file_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&DeviceSocketManager::StopListeningOnFILE, |
+ base::Unretained(this), |
+ socket_path, |
+ listener)); |
} |
void DeviceSocketManager::OnDataAvailable(const std::string& socket_path, |
const void* data) { |
CHECK_GT(socket_data_.count(socket_path), 0UL); |
DeviceSocketListeners& listeners = socket_data_[socket_path]->observers; |
- FOR_EACH_OBSERVER(DeviceSocketListener, listeners, OnDataAvailableOnIO(data)); |
+ FOR_EACH_OBSERVER( |
+ DeviceSocketListener, listeners, OnDataAvailableOnFILE(data)); |
} |
void DeviceSocketManager::CloseSocket(const std::string& socket_path) { |
@@ -202,10 +215,10 @@ void DeviceSocketManager::OnEOF(const std::string& socket_path) { |
CloseSocket(socket_path); |
} |
-void DeviceSocketManager::StartListeningOnIO(const std::string& socket_path, |
- size_t data_size, |
- DeviceSocketListener* listener) { |
- CHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
+void DeviceSocketManager::StartListeningOnFILE(const std::string& socket_path, |
+ size_t data_size, |
+ DeviceSocketListener* listener) { |
+ CHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
SocketData* socket_data = NULL; |
if (!socket_data_.count(socket_path)) { |
int socket_fd = -1; |
@@ -237,12 +250,12 @@ void DeviceSocketManager::StartListeningOnIO(const std::string& socket_path, |
socket_data->observers.AddObserver(listener); |
} |
-void DeviceSocketManager::StopListeningOnIO(const std::string& socket_path, |
- DeviceSocketListener* listener) { |
+void DeviceSocketManager::StopListeningOnFILE(const std::string& socket_path, |
+ DeviceSocketListener* listener) { |
if (!socket_data_.count(socket_path)) |
return; // Happens if unable to create a socket. |
- CHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
+ CHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
DeviceSocketListeners& listeners = socket_data_[socket_path]->observers; |
listeners.RemoveObserver(listener); |
if (!listeners.might_have_observers()) { |
@@ -251,6 +264,14 @@ void DeviceSocketManager::StopListeningOnIO(const std::string& socket_path, |
} |
} |
+void DeviceSocketManager::ScheduleDelete() { |
+ // Schedule a task to delete on FILE thread because |
+ // there may be a task scheduled on |file_task_runner_|. |
+ file_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&DeleteOnFILE, base::Unretained(this))); |
+} |
+ |
} // namespace |
DeviceSocketListener::DeviceSocketListener(const std::string& socket_path, |
@@ -265,8 +286,8 @@ DeviceSocketListener::~DeviceSocketListener() { |
// static |
void DeviceSocketListener::CreateSocketManager( |
- scoped_refptr<base::TaskRunner> io_task_runner) { |
- DeviceSocketManager::Create(io_task_runner); |
+ scoped_refptr<base::TaskRunner> file_task_runner) { |
+ DeviceSocketManager::Create(file_task_runner); |
} |
// static |
@@ -281,7 +302,9 @@ void DeviceSocketListener::StartListening() { |
} |
void DeviceSocketListener::StopListening() { |
- DeviceSocketManager::GetInstance()->StopListening(socket_path_, this); |
+ DeviceSocketManager* instance = DeviceSocketManager::GetInstanceUnsafe(); |
+ if (instance) |
+ instance->StopListening(socket_path_, this); |
} |
} // namespace athena |