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

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