Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / detail / impl / signal_set_service.ipp @ 2486

History | View | Annotate | Download (19.1 kB)

1
//
2
// detail/impl/signal_set_service.ipp
3
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
//
5
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6
//
7
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
//
10

    
11
#ifndef BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
12
#define BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
13

    
14
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15
# pragma once
16
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17

    
18
#include <boost/asio/detail/config.hpp>
19

    
20
#include <cstring>
21
#include <boost/asio/detail/reactor.hpp>
22
#include <boost/asio/detail/signal_blocker.hpp>
23
#include <boost/asio/detail/signal_set_service.hpp>
24
#include <boost/asio/detail/static_mutex.hpp>
25

    
26
#include <boost/asio/detail/push_options.hpp>
27

    
28
namespace boost {
29
namespace asio {
30
namespace detail {
31

    
32
struct signal_state
33
{
34
  // Mutex used for protecting global state.
35
  static_mutex mutex_;
36

    
37
  // The read end of the pipe used for signal notifications.
38
  int read_descriptor_;
39

    
40
  // The write end of the pipe used for signal notifications.
41
  int write_descriptor_;
42

    
43
  // Whether the signal state has been prepared for a fork.
44
  bool fork_prepared_;
45

    
46
  // The head of a linked list of all signal_set_service instances.
47
  class signal_set_service* service_list_;
48

    
49
  // A count of the number of objects that are registered for each signal.
50
  std::size_t registration_count_[max_signal_number];
51
};
52

    
53
signal_state* get_signal_state()
54
{
55
  static signal_state state = {
56
    BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };
57
  return &state;
58
}
59

    
60
void boost_asio_signal_handler(int signal_number)
61
{
62
#if defined(BOOST_ASIO_WINDOWS) \
63
  || defined(BOOST_ASIO_WINDOWS_RUNTIME) \
64
  || defined(__CYGWIN__)
65
  signal_set_service::deliver_signal(signal_number);
66
#else // defined(BOOST_ASIO_WINDOWS)
67
      //   || defined(BOOST_ASIO_WINDOWS_RUNTIME)
68
      //   || defined(__CYGWIN__)
69
  int saved_errno = errno;
70
  signal_state* state = get_signal_state();
71
  signed_size_type result = ::write(state->write_descriptor_,
72
      &signal_number, sizeof(signal_number));
73
  (void)result;
74
  errno = saved_errno;
75
#endif // defined(BOOST_ASIO_WINDOWS)
76
       //   || defined(BOOST_ASIO_WINDOWS_RUNTIME)
77
       //   || defined(__CYGWIN__)
78

    
79
#if defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION)
80
  ::signal(signal_number, boost_asio_signal_handler);
81
#endif // defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION)
82
}
83

    
84
#if !defined(BOOST_ASIO_WINDOWS) \
85
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
86
  && !defined(__CYGWIN__)
87
class signal_set_service::pipe_read_op : public reactor_op
88
{
89
public:
90
  pipe_read_op()
91
    : reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete)
92
  {
93
  }
94

    
95
  static bool do_perform(reactor_op*)
96
  {
97
    signal_state* state = get_signal_state();
98

    
99
    int fd = state->read_descriptor_;
100
    int signal_number = 0;
101
    while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
102
      if (signal_number >= 0 && signal_number < max_signal_number)
103
        signal_set_service::deliver_signal(signal_number);
104

    
105
    return false;
106
  }
107

    
108
  static void do_complete(io_service_impl* /*owner*/, operation* base,
109
      const boost::system::error_code& /*ec*/,
110
      std::size_t /*bytes_transferred*/)
111
  {
112
    pipe_read_op* o(static_cast<pipe_read_op*>(base));
113
    delete o;
114
  }
115
};
116
#endif // !defined(BOOST_ASIO_WINDOWS)
117
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
118
       //   && !defined(__CYGWIN__)
119

    
120
signal_set_service::signal_set_service(
121
    boost::asio::io_service& io_service)
122
  : io_service_(boost::asio::use_service<io_service_impl>(io_service)),
123
#if !defined(BOOST_ASIO_WINDOWS) \
124
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
125
  && !defined(__CYGWIN__)
126
    reactor_(boost::asio::use_service<reactor>(io_service)),
127
#endif // !defined(BOOST_ASIO_WINDOWS)
128
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
129
       //   && !defined(__CYGWIN__)
130
    next_(0),
131
    prev_(0)
132
{
133
  get_signal_state()->mutex_.init();
134

    
135
#if !defined(BOOST_ASIO_WINDOWS) \
136
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
137
  && !defined(__CYGWIN__)
138
  reactor_.init_task();
139
#endif // !defined(BOOST_ASIO_WINDOWS)
140
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
141
       //   && !defined(__CYGWIN__)
142

    
143
  for (int i = 0; i < max_signal_number; ++i)
144
    registrations_[i] = 0;
145

    
146
  add_service(this);
147
}
148

    
149
signal_set_service::~signal_set_service()
150
{
151
  remove_service(this);
152
}
153

    
154
void signal_set_service::shutdown_service()
155
{
156
  remove_service(this);
157

    
158
  op_queue<operation> ops;
159

    
160
  for (int i = 0; i < max_signal_number; ++i)
161
  {
162
    registration* reg = registrations_[i];
163
    while (reg)
164
    {
165
      ops.push(*reg->queue_);
166
      reg = reg->next_in_table_;
167
    }
168
  }
169

    
170
  io_service_.abandon_operations(ops);
171
}
172

    
173
void signal_set_service::fork_service(
174
    boost::asio::io_service::fork_event fork_ev)
175
{
176
#if !defined(BOOST_ASIO_WINDOWS) \
177
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
178
  && !defined(__CYGWIN__)
179
  signal_state* state = get_signal_state();
180
  static_mutex::scoped_lock lock(state->mutex_);
181

    
182
  switch (fork_ev)
183
  {
184
  case boost::asio::io_service::fork_prepare:
185
    {
186
      int read_descriptor = state->read_descriptor_;
187
      state->fork_prepared_ = true;
188
      lock.unlock();
189
      reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);
190
    }
191
    break;
192
  case boost::asio::io_service::fork_parent:
193
    if (state->fork_prepared_)
194
    {
195
      int read_descriptor = state->read_descriptor_;
196
      state->fork_prepared_ = false;
197
      lock.unlock();
198
      reactor_.register_internal_descriptor(reactor::read_op,
199
          read_descriptor, reactor_data_, new pipe_read_op);
200
    }
201
    break;
202
  case boost::asio::io_service::fork_child:
203
    if (state->fork_prepared_)
204
    {
205
      boost::asio::detail::signal_blocker blocker;
206
      close_descriptors();
207
      open_descriptors();
208
      int read_descriptor = state->read_descriptor_;
209
      state->fork_prepared_ = false;
210
      lock.unlock();
211
      reactor_.register_internal_descriptor(reactor::read_op,
212
          read_descriptor, reactor_data_, new pipe_read_op);
213
    }
214
    break;
215
  default:
216
    break;
217
  }
218
#else // !defined(BOOST_ASIO_WINDOWS)
219
      //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
220
      //   && !defined(__CYGWIN__)
221
  (void)fork_ev;
222
#endif // !defined(BOOST_ASIO_WINDOWS)
223
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
224
       //   && !defined(__CYGWIN__)
225
}
226

    
227
void signal_set_service::construct(
228
    signal_set_service::implementation_type& impl)
229
{
230
  impl.signals_ = 0;
231
}
232

    
233
void signal_set_service::destroy(
234
    signal_set_service::implementation_type& impl)
235
{
236
  boost::system::error_code ignored_ec;
237
  clear(impl, ignored_ec);
238
  cancel(impl, ignored_ec);
239
}
240

    
241
boost::system::error_code signal_set_service::add(
242
    signal_set_service::implementation_type& impl,
243
    int signal_number, boost::system::error_code& ec)
244
{
245
  // Check that the signal number is valid.
246
  if (signal_number < 0 || signal_number >= max_signal_number)
247
  {
248
    ec = boost::asio::error::invalid_argument;
249
    return ec;
250
  }
251

    
252
  signal_state* state = get_signal_state();
253
  static_mutex::scoped_lock lock(state->mutex_);
254

    
255
  // Find the appropriate place to insert the registration.
256
  registration** insertion_point = &impl.signals_;
257
  registration* next = impl.signals_;
258
  while (next && next->signal_number_ < signal_number)
259
  {
260
    insertion_point = &next->next_in_set_;
261
    next = next->next_in_set_;
262
  }
263

    
264
  // Only do something if the signal is not already registered.
265
  if (next == 0 || next->signal_number_ != signal_number)
266
  {
267
    registration* new_registration = new registration;
268

    
269
#if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
270
    // Register for the signal if we're the first.
271
    if (state->registration_count_[signal_number] == 0)
272
    {
273
# if defined(BOOST_ASIO_HAS_SIGACTION)
274
      using namespace std; // For memset.
275
      struct sigaction sa;
276
      memset(&sa, 0, sizeof(sa));
277
      sa.sa_handler = boost_asio_signal_handler;
278
      sigfillset(&sa.sa_mask);
279
      if (::sigaction(signal_number, &sa, 0) == -1)
280
# else // defined(BOOST_ASIO_HAS_SIGACTION)
281
      if (::signal(signal_number, boost_asio_signal_handler) == SIG_ERR)
282
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
283
      {
284
# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
285
        ec = boost::asio::error::invalid_argument;
286
# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
287
        ec = boost::system::error_code(errno,
288
            boost::asio::error::get_system_category());
289
# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
290
        delete new_registration;
291
        return ec;
292
      }
293
    }
294
#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
295

    
296
    // Record the new registration in the set.
297
    new_registration->signal_number_ = signal_number;
298
    new_registration->queue_ = &impl.queue_;
299
    new_registration->next_in_set_ = next;
300
    *insertion_point = new_registration;
301

    
302
    // Insert registration into the registration table.
303
    new_registration->next_in_table_ = registrations_[signal_number];
304
    if (registrations_[signal_number])
305
      registrations_[signal_number]->prev_in_table_ = new_registration;
306
    registrations_[signal_number] = new_registration;
307

    
308
    ++state->registration_count_[signal_number];
309
  }
310

    
311
  ec = boost::system::error_code();
312
  return ec;
313
}
314

    
315
boost::system::error_code signal_set_service::remove(
316
    signal_set_service::implementation_type& impl,
317
    int signal_number, boost::system::error_code& ec)
318
{
319
  // Check that the signal number is valid.
320
  if (signal_number < 0 || signal_number >= max_signal_number)
321
  {
322
    ec = boost::asio::error::invalid_argument;
323
    return ec;
324
  }
325

    
326
  signal_state* state = get_signal_state();
327
  static_mutex::scoped_lock lock(state->mutex_);
328

    
329
  // Find the signal number in the list of registrations.
330
  registration** deletion_point = &impl.signals_;
331
  registration* reg = impl.signals_;
332
  while (reg && reg->signal_number_ < signal_number)
333
  {
334
    deletion_point = &reg->next_in_set_;
335
    reg = reg->next_in_set_;
336
  }
337

    
338
  if (reg != 0 && reg->signal_number_ == signal_number)
339
  {
340
#if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
341
    // Set signal handler back to the default if we're the last.
342
    if (state->registration_count_[signal_number] == 1)
343
    {
344
# if defined(BOOST_ASIO_HAS_SIGACTION)
345
      using namespace std; // For memset.
346
      struct sigaction sa;
347
      memset(&sa, 0, sizeof(sa));
348
      sa.sa_handler = SIG_DFL;
349
      if (::sigaction(signal_number, &sa, 0) == -1)
350
# else // defined(BOOST_ASIO_HAS_SIGACTION)
351
      if (::signal(signal_number, SIG_DFL) == SIG_ERR)
352
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
353
      {
354
# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
355
        ec = boost::asio::error::invalid_argument;
356
# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
357
        ec = boost::system::error_code(errno,
358
            boost::asio::error::get_system_category());
359
# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
360
        return ec;
361
      }
362
    }
363
#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
364

    
365
    // Remove the registration from the set.
366
    *deletion_point = reg->next_in_set_;
367

    
368
    // Remove the registration from the registration table.
369
    if (registrations_[signal_number] == reg)
370
      registrations_[signal_number] = reg->next_in_table_;
371
    if (reg->prev_in_table_)
372
      reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
373
    if (reg->next_in_table_)
374
      reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
375

    
376
    --state->registration_count_[signal_number];
377

    
378
    delete reg;
379
  }
380

    
381
  ec = boost::system::error_code();
382
  return ec;
383
}
384

    
385
boost::system::error_code signal_set_service::clear(
386
    signal_set_service::implementation_type& impl,
387
    boost::system::error_code& ec)
388
{
389
  signal_state* state = get_signal_state();
390
  static_mutex::scoped_lock lock(state->mutex_);
391

    
392
  while (registration* reg = impl.signals_)
393
  {
394
#if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
395
    // Set signal handler back to the default if we're the last.
396
    if (state->registration_count_[reg->signal_number_] == 1)
397
    {
398
# if defined(BOOST_ASIO_HAS_SIGACTION)
399
      using namespace std; // For memset.
400
      struct sigaction sa;
401
      memset(&sa, 0, sizeof(sa));
402
      sa.sa_handler = SIG_DFL;
403
      if (::sigaction(reg->signal_number_, &sa, 0) == -1)
404
# else // defined(BOOST_ASIO_HAS_SIGACTION)
405
      if (::signal(reg->signal_number_, SIG_DFL) == SIG_ERR)
406
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
407
      {
408
# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
409
        ec = boost::asio::error::invalid_argument;
410
# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
411
        ec = boost::system::error_code(errno,
412
            boost::asio::error::get_system_category());
413
# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
414
        return ec;
415
      }
416
    }
417
#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
418

    
419
    // Remove the registration from the registration table.
420
    if (registrations_[reg->signal_number_] == reg)
421
      registrations_[reg->signal_number_] = reg->next_in_table_;
422
    if (reg->prev_in_table_)
423
      reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
424
    if (reg->next_in_table_)
425
      reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
426

    
427
    --state->registration_count_[reg->signal_number_];
428

    
429
    impl.signals_ = reg->next_in_set_;
430
    delete reg;
431
  }
432

    
433
  ec = boost::system::error_code();
434
  return ec;
435
}
436

    
437
boost::system::error_code signal_set_service::cancel(
438
    signal_set_service::implementation_type& impl,
439
    boost::system::error_code& ec)
440
{
441
  BOOST_ASIO_HANDLER_OPERATION(("signal_set", &impl, "cancel"));
442

    
443
  op_queue<operation> ops;
444
  {
445
    signal_state* state = get_signal_state();
446
    static_mutex::scoped_lock lock(state->mutex_);
447

    
448
    while (signal_op* op = impl.queue_.front())
449
    {
450
      op->ec_ = boost::asio::error::operation_aborted;
451
      impl.queue_.pop();
452
      ops.push(op);
453
    }
454
  }
455

    
456
  io_service_.post_deferred_completions(ops);
457

    
458
  ec = boost::system::error_code();
459
  return ec;
460
}
461

    
462
void signal_set_service::deliver_signal(int signal_number)
463
{
464
  signal_state* state = get_signal_state();
465
  static_mutex::scoped_lock lock(state->mutex_);
466

    
467
  signal_set_service* service = state->service_list_;
468
  while (service)
469
  {
470
    op_queue<operation> ops;
471

    
472
    registration* reg = service->registrations_[signal_number];
473
    while (reg)
474
    {
475
      if (reg->queue_->empty())
476
      {
477
        ++reg->undelivered_;
478
      }
479
      else
480
      {
481
        while (signal_op* op = reg->queue_->front())
482
        {
483
          op->signal_number_ = signal_number;
484
          reg->queue_->pop();
485
          ops.push(op);
486
        }
487
      }
488

    
489
      reg = reg->next_in_table_;
490
    }
491

    
492
    service->io_service_.post_deferred_completions(ops);
493

    
494
    service = service->next_;
495
  }
496
}
497

    
498
void signal_set_service::add_service(signal_set_service* service)
499
{
500
  signal_state* state = get_signal_state();
501
  static_mutex::scoped_lock lock(state->mutex_);
502

    
503
#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
504
  // If this is the first service to be created, open a new pipe.
505
  if (state->service_list_ == 0)
506
    open_descriptors();
507
#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
508

    
509
  // Insert service into linked list of all services.
510
  service->next_ = state->service_list_;
511
  service->prev_ = 0;
512
  if (state->service_list_)
513
    state->service_list_->prev_ = service;
514
  state->service_list_ = service;
515

    
516
#if !defined(BOOST_ASIO_WINDOWS) \
517
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
518
  && !defined(__CYGWIN__)
519
  // Register for pipe readiness notifications.
520
  int read_descriptor = state->read_descriptor_;
521
  lock.unlock();
522
  service->reactor_.register_internal_descriptor(reactor::read_op,
523
      read_descriptor, service->reactor_data_, new pipe_read_op);
524
#endif // !defined(BOOST_ASIO_WINDOWS)
525
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
526
       //   && !defined(__CYGWIN__)
527
}
528

    
529
void signal_set_service::remove_service(signal_set_service* service)
530
{
531
  signal_state* state = get_signal_state();
532
  static_mutex::scoped_lock lock(state->mutex_);
533

    
534
  if (service->next_ || service->prev_ || state->service_list_ == service)
535
  {
536
#if !defined(BOOST_ASIO_WINDOWS) \
537
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
538
  && !defined(__CYGWIN__)
539
    // Disable the pipe readiness notifications.
540
    int read_descriptor = state->read_descriptor_;
541
    lock.unlock();
542
    service->reactor_.deregister_descriptor(
543
        read_descriptor, service->reactor_data_, false);
544
    lock.lock();
545
#endif // !defined(BOOST_ASIO_WINDOWS)
546
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
547
       //   && !defined(__CYGWIN__)
548

    
549
    // Remove service from linked list of all services.
550
    if (state->service_list_ == service)
551
      state->service_list_ = service->next_;
552
    if (service->prev_)
553
      service->prev_->next_ = service->next_;
554
    if (service->next_)
555
      service->next_->prev_= service->prev_;
556
    service->next_ = 0;
557
    service->prev_ = 0;
558

    
559
#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
560
    // If this is the last service to be removed, close the pipe.
561
    if (state->service_list_ == 0)
562
      close_descriptors();
563
#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
564
  }
565
}
566

    
567
void signal_set_service::open_descriptors()
568
{
569
#if !defined(BOOST_ASIO_WINDOWS) \
570
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
571
  && !defined(__CYGWIN__)
572
  signal_state* state = get_signal_state();
573

    
574
  int pipe_fds[2];
575
  if (::pipe(pipe_fds) == 0)
576
  {
577
    state->read_descriptor_ = pipe_fds[0];
578
    ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);
579

    
580
    state->write_descriptor_ = pipe_fds[1];
581
    ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);
582

    
583
#if defined(FD_CLOEXEC)
584
    ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);
585
    ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);
586
#endif // defined(FD_CLOEXEC)
587
  }
588
  else
589
  {
590
    boost::system::error_code ec(errno,
591
        boost::asio::error::get_system_category());
592
    boost::asio::detail::throw_error(ec, "signal_set_service pipe");
593
  }
594
#endif // !defined(BOOST_ASIO_WINDOWS)
595
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
596
       //   && !defined(__CYGWIN__)
597
}
598

    
599
void signal_set_service::close_descriptors()
600
{
601
#if !defined(BOOST_ASIO_WINDOWS) \
602
  && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
603
  && !defined(__CYGWIN__)
604
  signal_state* state = get_signal_state();
605

    
606
  if (state->read_descriptor_ != -1)
607
    ::close(state->read_descriptor_);
608
  state->read_descriptor_ = -1;
609

    
610
  if (state->write_descriptor_ != -1)
611
    ::close(state->write_descriptor_);
612
  state->write_descriptor_ = -1;
613
#endif // !defined(BOOST_ASIO_WINDOWS)
614
       //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
615
       //   && !defined(__CYGWIN__)
616
}
617

    
618
void signal_set_service::start_wait_op(
619
    signal_set_service::implementation_type& impl, signal_op* op)
620
{
621
  io_service_.work_started();
622

    
623
  signal_state* state = get_signal_state();
624
  static_mutex::scoped_lock lock(state->mutex_);
625

    
626
  registration* reg = impl.signals_;
627
  while (reg)
628
  {
629
    if (reg->undelivered_ > 0)
630
    {
631
      --reg->undelivered_;
632
      op->signal_number_ = reg->signal_number_;
633
      io_service_.post_deferred_completion(op);
634
      return;
635
    }
636

    
637
    reg = reg->next_in_set_;
638
  }
639

    
640
  impl.queue_.push(op);
641
}
642

    
643
} // namespace detail
644
} // namespace asio
645
} // namespace boost
646

    
647
#include <boost/asio/detail/pop_options.hpp>
648

    
649
#endif // BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP