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

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