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

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