source: trunk/FACT++/src/fad.cc@ 11525

Last change on this file since 11525 was 11510, checked in by tbretz, 13 years ago
improvements to pulse simulation - needs optimization.
File size: 23.6 KB
Line 
1#include <iostream>
2#include <string>
3#include <boost/asio.hpp>
4#include <boost/bind.hpp>
5#include <boost/lexical_cast.hpp>
6#include <boost/asio/deadline_timer.hpp>
7#include <boost/enable_shared_from_this.hpp>
8
9using boost::lexical_cast;
10
11#include "Time.h"
12#include "Converter.h"
13
14#include "HeadersFAD.h"
15
16#include "dis.hxx"
17#include "Dim.h"
18
19using namespace std;
20using namespace FAD;
21
22namespace ba = boost::asio;
23namespace bs = boost::system;
24namespace dummy = ba::placeholders;
25
26using boost::lexical_cast;
27using ba::ip::tcp;
28
29class tcp_connection;
30
31class Trigger : public DimCommandHandler
32{
33 DimCommand fCmd;
34
35 vector<tcp_connection*> vec;
36
37public:
38 Trigger() : fCmd("FAD/TRIGGER", "I:1", this)
39 {
40 }
41
42 void Add(tcp_connection *ptr)
43 {
44 vec.push_back(ptr);
45 }
46
47 void Remove(tcp_connection *ptr)
48 {
49 vec.erase(find(vec.begin(), vec.end(), ptr));
50 }
51
52 void commandHandler();
53};
54
55// ------------------------------------------------------------------------
56
57class tcp_connection : public ba::ip::tcp::socket, public boost::enable_shared_from_this<tcp_connection>
58{
59public:
60 static Trigger fTrigger;
61
62 const int fBoardId;
63
64 double fStartTime;
65
66 void AsyncRead(ba::mutable_buffers_1 buffers)
67 {
68 ba::async_read(*this, buffers,
69 boost::bind(&tcp_connection::HandleReceivedData, shared_from_this(),
70 dummy::error, dummy::bytes_transferred));
71 }
72
73 void AsyncWrite(ba::ip::tcp::socket *socket, const ba::const_buffers_1 &buffers)
74 {
75 ba::async_write(*socket, buffers,
76 boost::bind(&tcp_connection::HandleSentData, shared_from_this(),
77 dummy::error, dummy::bytes_transferred));
78 }
79 void AsyncWait(ba::deadline_timer &timer, int seconds,
80 void (tcp_connection::*handler)(const bs::error_code&))// const
81 {
82 timer.expires_from_now(boost::posix_time::milliseconds(seconds));
83 timer.async_wait(boost::bind(handler, shared_from_this(), dummy::error));
84 }
85
86 // The constructor is prvate to force the obtained pointer to be shared
87 tcp_connection(ba::io_service& ioservice, int boardid) : ba::ip::tcp::socket(ioservice),
88 fBoardId(boardid), fRamRoi(kNumChannels), fTriggerSendData(ioservice),
89 fTriggerEnabled(false)
90 {
91 fTrigger.Add(this);
92 }
93 void PostTrigger(uint32_t triggerid)
94 {
95 if (fTriggerEnabled)
96 get_io_service().post(boost::bind(&tcp_connection::SendData, this, triggerid));
97 }
98
99 // Callback when writing was successfull or failed
100 void HandleSentData(const boost::system::error_code& error, size_t bytes_transferred)
101 {
102 cout << "Data sent: (transmitted=" << bytes_transferred << ") rc=" << error.message() << " (" << error << ")" << endl;
103 fOutQueue.pop_front();
104 }
105
106 vector<uint16_t> fBufCommand;
107
108 vector<uint16_t> fCommand;
109
110 FAD::EventHeader fHeader;
111 FAD::EventHeader fRam;
112 FAD::ChannelHeader fChHeader[kNumChannels];
113
114 vector<uint16_t> fRamRoi;
115
116 ba::deadline_timer fTriggerSendData;
117
118 bool fTriggerEnabled;
119 bool fCommandSocket;
120
121 int fSocket;
122
123 deque<vector<uint16_t>> fOutQueue;
124
125 void SendData(uint32_t triggerid)
126 {
127 fHeader.fPackageLength = sizeof(EventHeader)/2+1;
128 fHeader.fEventCounter++;
129 fHeader.fTriggerId = triggerid;
130 fHeader.fTimeStamp = uint32_t((Time(Time::utc).UnixTime()-fStartTime)*10000);
131 fHeader.fFreqRefClock = 997+rand()/(RAND_MAX/7);
132
133 for (int i=0; i<FAD::kNumTemp; i++)
134 fHeader.fTempDrs[i] = (42.+fBoardId/40.+float(rand())/RAND_MAX*5)*16;
135
136 vector<uint16_t> evtbuf;
137
138 for (int i=0; i<kNumChannels; i++)
139 {
140 fChHeader[i].fStartCell = i*10;
141
142 const vector<uint16_t> buf = fChHeader[i].HtoN();
143
144 evtbuf.insert(evtbuf.end(), buf.begin(), buf.end());
145 evtbuf.insert(evtbuf.end(), fChHeader[i].fRegionOfInterest, 0x42+i+fHeader.fDac[1]/32);
146
147 if (triggerid>0)
148 {
149 int p = 5.*rand()/RAND_MAX+20;
150 double rndm = 500.*rand()/RAND_MAX+500;
151 for (int ii=0; ii<fChHeader[i].fRegionOfInterest; ii++)
152 *(evtbuf.end()-fChHeader[i].fRegionOfInterest+ii) +=
153 rndm*exp(-0.5*(ii-p)*(ii-p)/25); // sigma=10
154 }
155
156 for (int ii=0; ii<fChHeader[i].fRegionOfInterest; ii++)
157 {
158 *(evtbuf.end()-fChHeader[i].fRegionOfInterest+ii) +=
159 6.*rand()/RAND_MAX + 5*exp(-ii/10); // sigma=10
160
161 *(evtbuf.end()-fChHeader[i].fRegionOfInterest+(ii+fChHeader[i].fStartCell)%fChHeader[i].fRegionOfInterest) +=
162 15*sin(2*3.1415*ii/512); // sigma=10
163 }
164
165
166 fHeader.fPackageLength += sizeof(ChannelHeader)/2;
167 fHeader.fPackageLength += fChHeader[i].fRegionOfInterest;
168 }
169
170 evtbuf.push_back(htons(FAD::kDelimiterEnd));
171
172 const vector<uint16_t> h = fHeader.HtoN();
173
174 evtbuf.insert(evtbuf.begin(), h.begin(), h.end());
175
176 fOutQueue.push_back(evtbuf);
177
178 if (fCommandSocket)
179 AsyncWrite(this, ba::buffer(ba::const_buffer(fOutQueue.back().data(), fOutQueue.back().size()*2)));
180 else
181 {
182 if (fSockets.size()==0)
183 return;
184
185 fSocket++;
186 fSocket %= fSockets.size();
187
188 AsyncWrite(fSockets[fSocket].get(), ba::buffer(ba::const_buffer(fOutQueue.back().data(), fOutQueue.back().size()*2)));
189 }
190 }
191
192 void TriggerSendData(const boost::system::error_code &ec)
193 {
194 if (!is_open())
195 {
196 // For example: Here we could schedule a new accept if we
197 // would not want to allow two connections at the same time.
198 return;
199 }
200
201 if (ec==ba::error::basic_errors::operation_aborted)
202 return;
203
204 // Check whether the deadline has passed. We compare the deadline
205 // against the current time since a new asynchronous operation
206 // may have moved the deadline before this actor had a chance
207 // to run.
208 if (fTriggerSendData.expires_at() > ba::deadline_timer::traits_type::now())
209 return;
210
211 // The deadline has passed.
212 if (fTriggerEnabled)
213 SendData(0);
214
215 AsyncWait(fTriggerSendData, fHeader.fTriggerGeneratorPrescaler, &tcp_connection::TriggerSendData);
216 }
217
218 void HandleReceivedData(const boost::system::error_code& error, size_t bytes_received)
219 {
220 // Do not schedule a new read if the connection failed.
221 if (bytes_received==0)
222 {
223 // Close the connection
224 close();
225 return;
226 }
227
228 // No command received yet
229 if (fCommand.size()==0)
230 {
231 transform(fBufCommand.begin(), fBufCommand.begin()+bytes_received/2,
232 fBufCommand.begin(), ntohs);
233
234 switch (fBufCommand[0])
235 {
236 case kCmdDrsEnable:
237 case kCmdDrsEnable+0x100:
238 fHeader.Enable(FAD::EventHeader::kDenable, fBufCommand[0]==kCmdDrsEnable);
239 cout << "-> DrsEnable " << fBoardId << " " << (fBufCommand[0]==kCmdDrsEnable) << endl;
240 break;
241
242 case kCmdDwrite:
243 case kCmdDwrite+0x100:
244 fHeader.Enable(FAD::EventHeader::kDwrite, fBufCommand[0]==kCmdDwrite);
245 cout << "-> Dwrite " << fBoardId << " " << (fBufCommand[0]==kCmdDwrite) << endl;
246 break;
247
248 case kCmdTriggerLine:
249 case kCmdTriggerLine+0x100:
250 cout << "-> Trigger line " << fBoardId << " " << (fBufCommand[0]==kCmdTriggerLine) << endl;
251 fTriggerEnabled = fBufCommand[0]==kCmdTriggerLine;
252 fHeader.Enable(FAD::EventHeader::kTriggerLine, fTriggerEnabled);
253 break;
254
255 case kCmdSclk:
256 case kCmdSclk+0x100:
257 cout << "-> Sclk " << fBoardId << endl;
258 fHeader.Enable(FAD::EventHeader::kSpiSclk, fBufCommand[0]==kCmdSclk);
259 break;
260
261 case kCmdSrclk:
262 case kCmdSrclk+0x100:
263 cout << "-> Drclk " << fBoardId << endl;
264 break;
265
266 case kCmdRun:
267 case kCmdRun+0x100:
268 fStartTime = Time(Time::utc).UnixTime();
269 cout << "-> Run " << fBoardId << endl;
270 break;
271
272 case kCmdBusy:
273 case kCmdBusy+0x100:
274 cout << "-> Busy " << fBoardId << " " << (fBufCommand[0]==kCmdBusy) << endl;
275 fHeader.Enable(FAD::EventHeader::kBusy, fBufCommand[0]==kCmdBusy);
276 break;
277
278 case kCmdSocket:
279 case kCmdSocket+0x100:
280 cout << "-> Socket " << fBoardId << " " << (fBufCommand[0]==kCmdSocket) << endl;
281 fCommandSocket = fBufCommand[0]==kCmdSocket;
282 fHeader.Enable(FAD::EventHeader::kSock17, !fCommandSocket);
283 break;
284
285 case kCmdContTrigger:
286 case kCmdContTrigger+0x100:
287 if (fBufCommand[0]==kCmdContTrigger)
288 AsyncWait(fTriggerSendData, 0, &tcp_connection::TriggerSendData);
289 else
290 fTriggerSendData.cancel();
291 fHeader.Enable(FAD::EventHeader::kContTrigger, fBufCommand[0]==kCmdContTrigger);
292 cout << "-> ContTrig " << fBoardId << " " << (fBufCommand[0]==kCmdContTrigger) << endl;
293 break;
294
295 case kCmdResetEventCounter:
296 cout << "-> ResetId " << fBoardId << endl;
297 fHeader.fEventCounter = 0;
298 break;
299
300 case kCmdSingleTrigger:
301 cout << "-> Trigger " << fBoardId << endl;
302 SendData(0);
303 break;
304
305 case kCmdWriteExecute:
306 cout << "-> Execute " << fBoardId << endl;
307 memcpy(fHeader.fDac, fRam.fDac, sizeof(fHeader.fDac));
308 for (int i=0; i<kNumChannels; i++)
309 fChHeader[i].fRegionOfInterest = fRamRoi[i];
310 fHeader.fRunNumber = fRam.fRunNumber;
311 break;
312
313 case kCmdWriteRunNumberMSW:
314 fCommand = fBufCommand;
315 break;
316
317 case kCmdWriteRunNumberLSW:
318 fCommand = fBufCommand;
319 break;
320
321 default:
322 if (fBufCommand[0]>=kCmdWriteRoi && fBufCommand[0]<kCmdWriteRoi+kNumChannels)
323 {
324 fCommand.resize(2);
325 fCommand[0] = kCmdWriteRoi;
326 fCommand[1] = fBufCommand[0]-kCmdWriteRoi;
327 break;
328 }
329 if (fBufCommand[0]>= kCmdWriteDac && fBufCommand[0]<kCmdWriteDac+kNumDac)
330 {
331 fCommand.resize(2);
332 fCommand[0] = kCmdWriteDac;
333 fCommand[1] = fBufCommand[0]-kCmdWriteDac;
334 break;
335 }
336 if (fBufCommand[0]==kCmdWriteRate)
337 {
338 fCommand.resize(1);
339 fCommand[0] = kCmdWriteRate;
340 break;
341 }
342
343 cout << "Received b=" << bytes_received << ": " << error.message() << " (" << error << ")" << endl;
344 cout << "Hex:" << Converter::GetHex<uint16_t>(&fBufCommand[0], bytes_received) << endl;
345 return;
346 }
347
348 fBufCommand.resize(1);
349 AsyncRead(ba::buffer(fBufCommand));
350 return;
351 }
352
353 transform(fBufCommand.begin(), fBufCommand.begin()+bytes_received/2,
354 fBufCommand.begin(), ntohs);
355
356 switch (fCommand[0])
357 {
358 case kCmdWriteRunNumberMSW:
359 fRam.fRunNumber &= 0xffff;
360 fRam.fRunNumber |= fBufCommand[0]<<16;
361 cout << "-> Set RunNumber " << fBoardId << " MSW" << endl;
362 break;
363 case kCmdWriteRunNumberLSW:
364 fRam.fRunNumber &= 0xffff0000;
365 fRam.fRunNumber |= fBufCommand[0];
366 cout << "-> Set RunNumber " << fBoardId << " LSW" << endl;
367 break;
368 case kCmdWriteRoi:
369 cout << "-> Set " << fBoardId << " Roi[" << fCommand[1] << "]=" << fBufCommand[0] << endl;
370 //fChHeader[fCommand[1]].fRegionOfInterest = fBufCommand[0];
371 fRamRoi[fCommand[1]] = fBufCommand[0];
372 break;
373
374 case kCmdWriteDac:
375 cout << "-> Set " << fBoardId << " Dac[" << fCommand[1] << "]=" << fBufCommand[0] << endl;
376 fRam.fDac[fCommand[1]] = fBufCommand[0];
377 break;
378
379 case kCmdWriteRate:
380 cout << "-> Set " << fBoardId << " Rate =" << fBufCommand[0] << endl;
381 fHeader.fTriggerGeneratorPrescaler = fBufCommand[0];
382 break;
383 }
384
385 fCommand.resize(0);
386
387 fBufCommand.resize(1);
388 AsyncRead(ba::buffer(fBufCommand));
389 }
390
391public:
392 typedef boost::shared_ptr<tcp_connection> shared_ptr;
393
394 static shared_ptr create(ba::io_service& io_service, int boardid)
395 {
396 return shared_ptr(new tcp_connection(io_service, boardid));
397 }
398
399 void start()
400 {
401 // Ownership of buffer must be valid until Handler is called.
402
403 fTriggerEnabled=false;
404 fCommandSocket=true;
405
406 fHeader.fStartDelimiter = FAD::kDelimiterStart;
407 fHeader.fVersion = 0x104;
408 fHeader.fBoardId = (fBoardId%10) | ((fBoardId/10)<<8);
409 fHeader.fRunNumber = 0;
410 fHeader.fDNA = reinterpret_cast<uint64_t>(this);
411 fHeader.fTriggerGeneratorPrescaler = 100;
412 fHeader.fStatus = 0xf<<12 |
413 FAD::EventHeader::kDenable |
414 FAD::EventHeader::kDwrite |
415 FAD::EventHeader::kDcmLocked |
416 FAD::EventHeader::kDcmReady |
417 FAD::EventHeader::kSpiSclk;
418
419
420 fStartTime = Time(Time::utc).UnixTime();
421
422 for (int i=0; i<kNumChannels; i++)
423 {
424 fChHeader[i].fId = (i%9) | ((i/9)<<4);
425 fChHeader[i].fRegionOfInterest = 0;
426 }
427
428 // Emit something to be written to the socket
429 fBufCommand.resize(1);
430 AsyncRead(ba::buffer(fBufCommand));
431
432// AsyncWait(fTriggerDynData, 1, &tcp_connection::SendDynData);
433
434// AsyncWrite(ba::buffer(ba::const_buffer(&fHeader, sizeof(FTM::Header))));
435// AsyncWait(deadline_, 3, &tcp_connection::check_deadline);
436
437 }
438
439 vector<boost::shared_ptr<ba::ip::tcp::socket>> fSockets;
440
441 ~tcp_connection()
442 {
443 fTrigger.Remove(this);
444 fSockets.clear();
445 }
446
447 void handle_accept(boost::shared_ptr<ba::ip::tcp::socket> socket, int port, const boost::system::error_code&/* error*/)
448 {
449 cout << this << " Added one socket[" << fBoardId << "] " << socket->remote_endpoint().address().to_v4().to_string();
450 cout << ":"<< port << endl;
451 fSockets.push_back(socket);
452 }
453};
454
455Trigger tcp_connection::fTrigger;
456
457void Trigger::commandHandler()
458{
459 if (!getCommand())
460 return;
461
462 for (vector<tcp_connection*>::iterator it=vec.begin();
463 it!=vec.end(); it++)
464 (*it)->PostTrigger(getCommand()->getInt());
465}
466
467
468class tcp_server
469{
470 tcp::acceptor acc0;
471 tcp::acceptor acc1;
472 tcp::acceptor acc2;
473 tcp::acceptor acc3;
474 tcp::acceptor acc4;
475 tcp::acceptor acc5;
476 tcp::acceptor acc6;
477 tcp::acceptor acc7;
478
479 int fBoardId;
480
481public:
482 tcp_server(ba::io_service& ioservice, int port, int board) :
483 acc0(ioservice, tcp::endpoint(tcp::v4(), port)),
484 acc1(ioservice, tcp::endpoint(tcp::v4(), port+1)),
485 acc2(ioservice, tcp::endpoint(tcp::v4(), port+2)),
486 acc3(ioservice, tcp::endpoint(tcp::v4(), port+3)),
487 acc4(ioservice, tcp::endpoint(tcp::v4(), port+4)),
488 acc5(ioservice, tcp::endpoint(tcp::v4(), port+5)),
489 acc6(ioservice, tcp::endpoint(tcp::v4(), port+6)),
490 acc7(ioservice, tcp::endpoint(tcp::v4(), port+7)),
491 fBoardId(board)
492 {
493 // We could start listening for more than one connection
494 // here, but since there is only one handler executed each time
495 // it would not make sense. Before one handle_accept is not
496 // finished no new handle_accept will be called.
497 // Workround: Start a new thread in handle_accept
498 start_accept();
499 }
500
501private:
502 void start_accept(tcp_connection::shared_ptr dest, tcp::acceptor &acc)
503 {
504 boost::shared_ptr<ba::ip::tcp::socket> connection =
505 boost::shared_ptr<ba::ip::tcp::socket>(new ba::ip::tcp::socket(acc.io_service()));
506
507 acc.async_accept(*connection,
508 boost::bind(&tcp_connection::handle_accept,
509 dest, connection,
510 acc.local_endpoint().port(),
511 ba::placeholders::error));
512 }
513
514 void start_accept()
515 {
516 cout << "Start accept[" << fBoardId << "] " << acc0.local_endpoint().port() << "..." << flush;
517 tcp_connection::shared_ptr new_connection = tcp_connection::create(/*acceptor_.*/acc0.io_service(), fBoardId);
518
519 cout << new_connection.get() << " ";
520
521 // This will accept a connection without blocking
522 acc0.async_accept(*new_connection,
523 boost::bind(&tcp_server::handle_accept,
524 this,
525 new_connection,
526 ba::placeholders::error));
527
528 start_accept(new_connection, acc1);
529 start_accept(new_connection, acc2);
530 start_accept(new_connection, acc3);
531 start_accept(new_connection, acc4);
532 start_accept(new_connection, acc5);
533 start_accept(new_connection, acc6);
534 start_accept(new_connection, acc7);
535
536 cout << "start-done." << endl;
537 }
538
539 void handle_accept(tcp_connection::shared_ptr new_connection, const boost::system::error_code& error)
540 {
541 // The connection has been accepted and is now ready to use
542
543 // not installing a new handler will stop run()
544 cout << new_connection.get() << " Handle accept[" << fBoardId << "]["<<new_connection->fBoardId<<"]..." << flush;
545 if (!error)
546 {
547 new_connection->start();
548
549 // The is now an open connection/server (tcp_connection)
550 // we immediatly schedule another connection
551 // This allowed two client-connection at the same time
552 start_accept();
553 }
554 cout << "handle-done." << endl;
555 }
556};
557
558#include "Configuration.h"
559
560void SetupConfiguration(::Configuration &conf)
561{
562 const string n = conf.GetName()+".log";
563
564 po::options_description config("Program options");
565 config.add_options()
566 ("dns", var<string>("localhost"), "Dim nameserver host name (Overwites DIM_DNS_NODE environment variable)")
567 ("port,p", var<uint16_t>(4000), "")
568 ("num,n", var<uint16_t>(40), "")
569 ;
570
571 po::positional_options_description p;
572 p.add("port", 1); // The first positional options
573 p.add("num", 1); // The second positional options
574
575 conf.AddEnv("dns", "DIM_DNS_NODE");
576
577 conf.AddOptions(config);
578 conf.SetArgumentPositions(p);
579}
580
581int main(int argc, const char **argv)
582{
583 ::Configuration conf(argv[0]);
584
585 SetupConfiguration(conf);
586
587 po::variables_map vm;
588 try
589 {
590 vm = conf.Parse(argc, argv);
591 }
592#if BOOST_VERSION > 104000
593 catch (po::multiple_occurrences &e)
594 {
595 cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
596 return -1;
597 }
598#endif
599 catch (exception& e)
600 {
601 cerr << "Program options invalid due to: " << e.what() << endl;
602 return -1;
603 }
604
605 if (conf.HasVersion() || conf.HasPrint() || conf.HasHelp())
606 return -1;
607
608 Dim::Setup(conf.Get<string>("dns"));
609
610 DimServer::start("FAD");
611
612 //try
613 {
614 ba::io_service io_service;
615
616 const uint16_t n = conf.Get<uint16_t>("num");
617 uint16_t port = conf.Get<uint16_t>("port");
618
619 vector<shared_ptr<tcp_server>> servers;
620
621 for (int i=0; i<n; i++)
622 {
623 shared_ptr<tcp_server> server(new tcp_server(io_service, port, i));
624 servers.push_back(server);
625
626 port += 8;
627 }
628
629 // ba::add_service(io_service, &server);
630 // server.add_service(...);
631 //cout << "Run..." << flush;
632
633 // Calling run() from a single thread ensures no concurrent access
634 // of the handler which are called!!!
635 io_service.run();
636
637 //cout << "end." << endl;
638 }
639 /*catch (std::exception& e)
640 {
641 std::cerr << e.what() << std::endl;
642 }*/
643
644 return 0;
645}
646/* ====================== Buffers ===========================
647
648char d1[128]; ba::buffer(d1));
649std::vector<char> d2(128); ba::buffer(d2);
650boost::array<char, 128> d3; by::buffer(d3);
651
652// --------------------------------
653char d1[128];
654std::vector<char> d2(128);
655boost::array<char, 128> d3;
656
657boost::array<mutable_buffer, 3> bufs1 = {
658 ba::buffer(d1),
659 ba::buffer(d2),
660 ba::buffer(d3) };
661sock.read(bufs1);
662
663std::vector<const_buffer> bufs2;
664bufs2.push_back(boost::asio::buffer(d1));
665bufs2.push_back(boost::asio::buffer(d2));
666bufs2.push_back(boost::asio::buffer(d3));
667sock.write(bufs2);
668
669
670// ======================= Read functions =========================
671
672ba::async_read_until --> delimiter
673
674streambuf buf; // Ensure validity until handler!
675by::async_read(s, buf, ....);
676
677ba::async_read(s, ba:buffer(data, size), handler);
678 // Single buffer
679 boost::asio::async_read(s,
680 ba::buffer(data, size),
681 compl-func --> ba::transfer_at_least(32),
682 handler);
683
684 // Multiple buffers
685boost::asio::async_read(s, buffers,
686 compl-func --> boost::asio::transfer_all(),
687 handler);
688 */
689
690// ================= Others ===============================
691
692 /*
693 strand Provides serialised handler execution.
694 work Class to inform the io_service when it has work to do.
695
696
697io_service::
698dispatch Request the io_service to invoke the given handler.
699poll Run the io_service's event processing loop to execute ready
700 handlers.
701poll_one Run the io_service's event processing loop to execute one ready
702 handler.
703post Request the io_service to invoke the given handler and return
704 immediately.
705reset Reset the io_service in preparation for a subsequent run()
706 invocation.
707run Run the io_service's event processing loop.
708run_one Run the io_service's event processing loop to execute at most
709 one handler.
710stop Stop the io_service's event processing loop.
711wrap Create a new handler that automatically dispatches the wrapped
712 handler on the io_service.
713
714strand:: The io_service::strand class provides the ability to
715 post and dispatch handlers with the guarantee that none
716 of those handlers will execute concurrently.
717
718dispatch Request the strand to invoke the given handler.
719get_io_service Get the io_service associated with the strand.
720post Request the strand to invoke the given handler and return
721 immediately.
722wrap Create a new handler that automatically dispatches the
723 wrapped handler on the strand.
724
725work:: The work class is used to inform the io_service when
726 work starts and finishes. This ensures that the io_service's run() function will not exit while work is underway, and that it does exit when there is no unfinished work remaining.
727get_io_service Get the io_service associated with the work.
728work Constructor notifies the io_service that work is starting.
729
730*/
731
732
Note: See TracBrowser for help on using the repository browser.