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

Side by Side Diff: net/socket/tcp_pinger.h

Issue 3368012: Wait on a pipe for the test server to start up (Closed)
Patch Set: Sigh. Rebase onto trunk. Created 10 years, 3 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 unified diff | Download patch
« no previous file with comments | « net/net.gyp ('k') | net/socket/tcp_pinger_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 #ifndef NET_SOCKET_TCP_PINGER_H_
6 #define NET_SOCKET_TCP_PINGER_H_
7 #pragma once
8
9 #include "base/compiler_specific.h"
10 #include "base/ref_counted.h"
11 #include "base/scoped_ptr.h"
12 #include "base/task.h"
13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
14 #include "base/thread.h"
15 #include "base/waitable_event.h"
16 #include "net/base/address_list.h"
17 #include "net/base/completion_callback.h"
18 #include "net/base/net_errors.h"
19 #include "net/socket/tcp_client_socket.h"
20
21 namespace base {
22 class TimeDelta;
23 }
24
25 namespace net {
26
27 // Simple class to wait until a TCP server is accepting connections.
28 class TCPPinger {
29 public:
30 explicit TCPPinger(const net::AddressList& addr)
31 : io_thread_("TCPPinger"),
32 worker_(new Worker(addr)) {
33 worker_->AddRef();
34 // Start up a throwaway IO thread just for this.
35 // TODO(dkegel): use some existing thread pool instead?
36 base::Thread::Options options;
37 options.message_loop_type = MessageLoop::TYPE_IO;
38 io_thread_.StartWithOptions(options);
39 }
40
41 ~TCPPinger() {
42 io_thread_.message_loop()->ReleaseSoon(FROM_HERE, worker_);
43 }
44
45 int Ping() {
46 // Default is 10 tries, each with a timeout of 1000ms,
47 // for a total max timeout of 10 seconds.
48 return Ping(base::TimeDelta::FromMilliseconds(1000), 10);
49 }
50
51 int Ping(base::TimeDelta tryTimeout, int nTries) {
52 int err = ERR_IO_PENDING;
53 // Post a request to do the connect on that thread.
54 for (int i = 0; i < nTries; i++) {
55 io_thread_.message_loop()->PostTask(FROM_HERE,
56 NewRunnableMethod(worker_,
57 &net::TCPPinger::Worker::DoConnect));
58 // Timeout here in case remote host offline
59 err = worker_->TimedWaitForResult(tryTimeout);
60 if (err == net::OK)
61 break;
62 PlatformThread::Sleep(static_cast<int>(tryTimeout.InMilliseconds()));
63
64 // Cancel leftover activity, if any
65 io_thread_.message_loop()->PostTask(FROM_HERE,
66 NewRunnableMethod(worker_,
67 &net::TCPPinger::Worker::DoDisconnect));
68 worker_->WaitForResult();
69 }
70 return err;
71 }
72
73 private:
74
75 // Inner class to handle all actual socket calls.
76 // This makes the outer interface simpler,
77 // and helps us obey the "all socket calls
78 // must be on same thread" restriction.
79 class Worker : public base::RefCountedThreadSafe<Worker> {
80 public:
81 explicit Worker(const net::AddressList& addr)
82 : event_(false, false),
83 net_error_(ERR_IO_PENDING),
84 addr_(addr),
85 ALLOW_THIS_IN_INITIALIZER_LIST(connect_callback_(this,
86 &net::TCPPinger::Worker::ConnectDone)) {
87 }
88
89 void DoConnect() {
90 sock_.reset(new TCPClientSocket(addr_, NULL, net::NetLog::Source()));
91 int rv = sock_->Connect(&connect_callback_);
92 // Regardless of success or failure, if we're done now,
93 // signal the customer.
94 if (rv != ERR_IO_PENDING)
95 ConnectDone(rv);
96 }
97
98 void DoDisconnect() {
99 sock_.reset();
100 event_.Signal();
101 }
102
103 void ConnectDone(int rv) {
104 sock_.reset();
105 net_error_ = rv;
106 event_.Signal();
107 }
108
109 int TimedWaitForResult(base::TimeDelta tryTimeout) {
110 event_.TimedWait(tryTimeout);
111 // In case of timeout, the value of net_error_ should be ERR_IO_PENDING.
112 // However, a harmless data race can happen if TimedWait times out right
113 // before event_.Signal() is called in ConnectDone().
114 return ANNOTATE_UNPROTECTED_READ(net_error_);
115 }
116
117 int WaitForResult() {
118 event_.Wait();
119 return net_error_;
120 }
121
122 private:
123 friend class base::RefCountedThreadSafe<Worker>;
124
125 ~Worker() {}
126
127 base::WaitableEvent event_;
128 int net_error_;
129 net::AddressList addr_;
130 scoped_ptr<TCPClientSocket> sock_;
131 net::CompletionCallbackImpl<Worker> connect_callback_;
132 };
133
134 base::Thread io_thread_;
135 Worker* worker_;
136 DISALLOW_COPY_AND_ASSIGN(TCPPinger);
137 };
138
139 } // namespace net
140
141 #endif // NET_SOCKET_TCP_PINGER_H_
OLDNEW
« no previous file with comments | « net/net.gyp ('k') | net/socket/tcp_pinger_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698