1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "device/bluetooth/bluetooth_socket_thread.h"
6
7#include "base/lazy_instance.h"
8#include "base/sequenced_task_runner.h"
9#include "base/threading/thread.h"
10
11namespace device {
12
13base::LazyInstance<scoped_refptr<BluetoothSocketThread> > g_instance =
14    LAZY_INSTANCE_INITIALIZER;
15
16// static
17scoped_refptr<BluetoothSocketThread> BluetoothSocketThread::Get() {
18  if (!g_instance.Get().get()) {
19    g_instance.Get() = new BluetoothSocketThread();
20  }
21  return g_instance.Get();
22}
23
24// static
25void BluetoothSocketThread::CleanupForTesting() {
26  DCHECK(g_instance.Get().get());
27  g_instance.Get() = NULL;
28}
29
30BluetoothSocketThread::BluetoothSocketThread()
31    : active_socket_count_(0) {}
32
33BluetoothSocketThread::~BluetoothSocketThread() {
34  if (thread_) {
35    thread_->Stop();
36    thread_.reset(NULL);
37    task_runner_ = NULL;
38  }
39}
40
41void BluetoothSocketThread::OnSocketActivate() {
42  DCHECK(thread_checker_.CalledOnValidThread());
43  active_socket_count_++;
44  EnsureStarted();
45}
46
47void BluetoothSocketThread::OnSocketDeactivate() {
48  DCHECK(thread_checker_.CalledOnValidThread());
49  active_socket_count_--;
50  if (active_socket_count_ == 0 && thread_) {
51    thread_->Stop();
52    thread_.reset(NULL);
53    task_runner_ = NULL;
54  }
55}
56
57void BluetoothSocketThread::EnsureStarted() {
58  DCHECK(thread_checker_.CalledOnValidThread());
59  if (thread_)
60    return;
61
62  base::Thread::Options thread_options;
63  thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
64  thread_.reset(new base::Thread("BluetoothSocketThread"));
65  thread_->StartWithOptions(thread_options);
66  task_runner_ = thread_->message_loop_proxy();
67}
68
69scoped_refptr<base::SequencedTaskRunner> BluetoothSocketThread::task_runner()
70    const {
71  DCHECK(active_socket_count_ > 0);
72  DCHECK(thread_);
73  DCHECK(task_runner_.get());
74
75  return task_runner_;
76}
77
78}  // namespace device
79