Merge lp:~fpstovall/nrtb/bk2thefuture into lp:nrtb
- bk2thefuture
- Merge into alpha
Status: | Merged |
---|---|
Approved by: | Rick Stovall |
Approved revision: | 53 |
Merged at revision: | 15 |
Proposed branch: | lp:~fpstovall/nrtb/bk2thefuture |
Merge into: | lp:nrtb |
Diff against target: |
7286 lines (+3314/-2762) 42 files modified
cpp/common/Makefile (+7/-8) cpp/common/abs_queue/Makefile (+33/-0) cpp/common/abs_queue/abs_queue.h (+187/-0) cpp/common/abs_queue/abs_queue_test.cpp (+120/-0) cpp/common/circular_queue/Makefile (+4/-2) cpp/common/circular_queue/circular_queue.h (+23/-128) cpp/common/circular_queue/circular_queue_test.cpp (+47/-81) cpp/common/common_rl/Makefile (+6/-3) cpp/common/common_rl/common.cpp (+168/-192) cpp/common/common_rl/common.h (+29/-33) cpp/common/common_rl/common_rl_test.cpp (+18/-0) cpp/common/confreader/Makefile (+5/-3) cpp/common/confreader/confreader.cpp (+140/-148) cpp/common/confreader/confreader.h (+234/-233) cpp/common/confreader/conftest.cpp (+54/-48) cpp/common/linear_queue/Makefile (+4/-2) cpp/common/linear_queue/linear_queue.h (+6/-117) cpp/common/linear_queue/linear_queue_test.cpp (+52/-85) cpp/common/logger/Makefile (+20/-22) cpp/common/logger/logger.cpp (+141/-0) cpp/common/logger/logger.h (+76/-0) cpp/common/logger/logger_test.cpp (+105/-0) cpp/common/point/Makefile (+4/-5) cpp/common/point/common_test.cpp (+65/-65) cpp/common/point/triad.h (+176/-176) cpp/common/serializer/Makefile (+2/-2) cpp/common/serializer/serializer.cpp (+0/-2) cpp/common/serializer/serializer.h (+3/-3) cpp/common/singleton/Makefile (+3/-2) cpp/common/singleton/singleton.h (+64/-60) cpp/common/singleton/singleton_test.cpp (+8/-7) cpp/common/sockets/Makefile (+5/-3) cpp/common/sockets/base_socket.cpp (+565/-598) cpp/common/sockets/base_socket.h (+472/-528) cpp/common/sockets/socket_test.cpp (+53/-87) cpp/common/timer/Makefile (+38/-0) cpp/common/timer/hires_timer.cpp (+174/-0) cpp/common/timer/hires_timer.h (+131/-0) cpp/common/timer/timer_test.cpp (+72/-0) obsolete/Cpp/common/logger/log_setup.cpp (+0/-43) obsolete/Cpp/common/logger/log_setup.h (+0/-30) obsolete/Cpp/common/logger/log_test.cpp (+0/-46) |
To merge this branch: | bzr merge lp:~fpstovall/nrtb/bk2thefuture |
Related bugs: | |
Related blueprints: |
Update C++ Common libs to C++11
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Rick Stovall | code merge | Approve | |
Review via email: mp+179547@code.launchpad.net |
Commit message
Description of the change
This branch moves our development focus back to C++ (C++11). In preparing for this, the following has been accomplished:
* The D code has been moved to the "obsolete" directory.
* The needed C++ common libs have been restored from the obsolete directory.
* Threading now uses the C++11 model; the old thread class has been removed.
* The work_queue template has been replaced by cleaner thread safe queues.
* The tcp_server_socket factory has been redesigned to use a producer/consumer model.
* There is a new logger class which is simple and fast.
* All the common code has been reviewed, formatted neatly, and updated to C++11 standards.
The upshot of all this is that we are closer to a working alpha phase release now than at any time in the last couple of years. I intend to allow this to rest until Sunday, at which time I will promoted it to main branch if there are no objections.
Preview Diff
1 | === renamed directory 'obsolete/Cpp' => 'cpp' |
2 | === modified file 'cpp/common/Makefile' |
3 | --- obsolete/Cpp/common/Makefile 2011-12-14 19:24:03 +0000 |
4 | +++ cpp/common/Makefile 2013-08-09 21:47:12 +0000 |
5 | @@ -16,7 +16,7 @@ |
6 | # |
7 | #*********************************************** |
8 | |
9 | -lib: ./lib/nrtb_common.a ./lib/nrtb_communication.a |
10 | +lib: ./lib/nrtb_common.a |
11 | |
12 | ./lib/nrtb_common.a: |
13 | @echo "============= building common libs ===============" |
14 | @@ -24,9 +24,6 @@ |
15 | @ar -r ./lib/nrtb_common.a ./obj/*.o |
16 | @echo "============= common libs complete ===============" |
17 | |
18 | -./lib/nrtb_communication.a: |
19 | - @cd comm_handlers; make lib |
20 | - |
21 | modules: |
22 | @echo "============= building common modules ===============" |
23 | @make doit |
24 | @@ -36,14 +33,13 @@ |
25 | @echo "============= cleaning common libs ===============" |
26 | @make action=clean doit |
27 | @rm -fv ./obj/* ./lib/* ./include/* |
28 | - @cd comm_handlers; make clean |
29 | @echo "========== common lib cleanup complete ===========" |
30 | |
31 | doit: |
32 | @cd common_rl; make ${action} |
33 | @cd point; make ${action} |
34 | @cd timer; make ${action} |
35 | - @cd threads; make ${action} |
36 | + @cd abs_queue; make ${action} |
37 | @cd circular_queue; make ${action} |
38 | @cd linear_queue; make ${action} |
39 | @cd sockets; make ${action} |
40 | @@ -51,6 +47,9 @@ |
41 | @cd singleton; make ${action} |
42 | @cd logger; make ${action} |
43 | @cd confreader; make ${action} |
44 | - @cd GPB; make ${action} |
45 | - @cd transceiver; make ${action} |
46 | + |
47 | +# --- the following are obsolete and may be removed later. |
48 | +# @cd threads; make ${action} |
49 | +# @cd GPB; make ${action} |
50 | +# @cd transceiver; make ${action} |
51 | |
52 | |
53 | === added directory 'cpp/common/abs_queue' |
54 | === added file 'cpp/common/abs_queue/Makefile' |
55 | --- cpp/common/abs_queue/Makefile 1970-01-01 00:00:00 +0000 |
56 | +++ cpp/common/abs_queue/Makefile 2013-08-09 21:47:12 +0000 |
57 | @@ -0,0 +1,33 @@ |
58 | +#*********************************************** |
59 | +#This file is part of the NRTB project (https://launchpad.net/nrtb). |
60 | +# |
61 | +# NRTB is free software: you can redistribute it and/or modify |
62 | +# it under the terms of the GNU General Public License as published by |
63 | +# the Free Software Foundation, either version 3 of the License, or |
64 | +# (at your option) any later version. |
65 | +# |
66 | +# NRTB is distributed in the hope that it will be useful, |
67 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
68 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
69 | +# GNU General Public License for more details. |
70 | +# |
71 | +# You should have received a copy of the GNU General Public License |
72 | +# along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
73 | +# |
74 | +#*********************************************** |
75 | + |
76 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
77 | + |
78 | +lib: abs_queue_test |
79 | + @./abs_queue_test |
80 | + @cp -v abs_queue.h ../include |
81 | + @echo build complete |
82 | + |
83 | +abs_queue_test: abs_queue.h abs_queue_test.cpp |
84 | + @rm -f abs_queue_test |
85 | + g++ -c abs_queue_test.cpp -I../include ${switches} |
86 | + g++ -o abs_queue_test abs_queue_test.o -lpthread ${switches} |
87 | + |
88 | +clean: |
89 | + @rm -rvf *.o abs_queue_test ../include/abs_queue.h *.log ../obj/abs_queue.o |
90 | + @echo all objects and executables have been erased. |
91 | |
92 | === added file 'cpp/common/abs_queue/abs_queue.h' |
93 | --- cpp/common/abs_queue/abs_queue.h 1970-01-01 00:00:00 +0000 |
94 | +++ cpp/common/abs_queue/abs_queue.h 2013-08-09 21:47:12 +0000 |
95 | @@ -0,0 +1,187 @@ |
96 | +/*********************************************** |
97 | + This file is part of the NRTB project (https://*launchpad.net/nrtb). |
98 | + |
99 | + NRTB is free software: you can redistribute it and/or modify |
100 | + it under the terms of the GNU General Public License as published by |
101 | + the Free Software Foundation, either version 3 of the License, or |
102 | + (at your option) any later version. |
103 | + |
104 | + NRTB is distributed in the hope that it will be useful, |
105 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
106 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
107 | + GNU General Public License for more details. |
108 | + |
109 | + You should have received a copy of the GNU General Public License |
110 | + along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
111 | + |
112 | + **********************************************/ |
113 | + |
114 | +#ifndef nrtb_abs_queue_h |
115 | +#define nrtb_abs_queue_h |
116 | + |
117 | +#include <common.h> |
118 | +#include <atomic> |
119 | +#include <mutex> |
120 | +#include <condition_variable> |
121 | + |
122 | +namespace nrtb |
123 | +{ |
124 | + |
125 | +/******************************************************** |
126 | + * The abs_queue template is designed for use with |
127 | + * the classic producer/consumer thread management model. |
128 | + * The producer uses abs_queue::push() to put items |
129 | + * in the queue as they become available, and the consumer |
130 | + * thread calls abs_queue::park() when it is ready |
131 | + * for the next item to work. |
132 | + * |
133 | + * This queue will expand as needed. Constrast this with |
134 | + * the circular_queue, which is of a fixed size and will |
135 | + * drop older data when full |
136 | + * |
137 | + * Common uses would be for buffering outgoing or incomming |
138 | + * messages from a communications channel, providing a feed |
139 | + * queue for parallel threads to make full use of multi-core |
140 | + * processors, or any case where one or more threads are |
141 | + * passing data to another set of threads. |
142 | +********************************************************/ |
143 | +template <class T, class queue_t> |
144 | +class abs_queue |
145 | +{ |
146 | +public: |
147 | + class queue_not_ready: public nrtb::base_exception {}; |
148 | + |
149 | + /// Total number of items placed in queue. |
150 | + std::atomic<int> in_count {0}; |
151 | + /// Total number of items read from queue. |
152 | + std::atomic<int> out_count {0}; |
153 | + |
154 | + /********************************************* |
155 | + * creates the queue with the specified |
156 | + * number of elements. |
157 | + *********************************************/ |
158 | + abs_queue(); |
159 | + |
160 | + /********************************************* |
161 | + * releases all items in the queue |
162 | + *********************************************/ |
163 | + ~abs_queue(); |
164 | + |
165 | + /********************************************* |
166 | + * Puts an item in the queue. |
167 | + *********************************************/ |
168 | + void push(T item); |
169 | + |
170 | + /********************************************* |
171 | + * Pops the next item off the queue, blocking |
172 | + * if needed until an item becomes available. |
173 | + *********************************************/ |
174 | + T pop(); |
175 | + |
176 | + /********************************************* |
177 | + * puts the queue in shutdown mode. |
178 | + *********************************************/ |
179 | + void shutdown(); |
180 | + |
181 | + // returns the number of items in the queue |
182 | + int size(); |
183 | + // resizes the buffer, may cause data loss |
184 | + void resize(int newsize); |
185 | + // clears the buffer, data will be discarded. |
186 | + void clear(); |
187 | + |
188 | +protected: |
189 | + |
190 | + queue_t buffer; |
191 | + std::mutex mylock; |
192 | + std::condition_variable signal; |
193 | + bool ready {true}; |
194 | +}; |
195 | + |
196 | +template <class T, class queue_t> |
197 | +abs_queue<T,queue_t>::abs_queue() |
198 | +{ |
199 | +}; |
200 | + |
201 | +template <class T, class queue_t> |
202 | +abs_queue<T,queue_t>::~abs_queue() |
203 | +{ |
204 | + shutdown(); |
205 | +}; |
206 | + |
207 | +template <class T, class queue_t> |
208 | +void abs_queue<T,queue_t>::push(T item) |
209 | +{ |
210 | + if (ready) |
211 | + { |
212 | + in_count++; |
213 | + { |
214 | + std::unique_lock<std::mutex> lock(mylock); |
215 | + buffer.push(item); |
216 | + } |
217 | + signal.notify_one(); |
218 | + } |
219 | + else |
220 | + { |
221 | + queue_not_ready e; |
222 | + throw e; |
223 | + } |
224 | +}; |
225 | + |
226 | +template <class T, class queue_t> |
227 | +T abs_queue<T,queue_t>::pop() |
228 | +{ |
229 | + std::unique_lock<std::mutex> lock(mylock); |
230 | + while (buffer.empty() && ready) |
231 | + signal.wait(lock); |
232 | + if (ready) |
233 | + { |
234 | + T returnme = buffer.front(); |
235 | + buffer.pop(); |
236 | + out_count++; |
237 | + return returnme; |
238 | + } |
239 | + else |
240 | + { |
241 | + queue_not_ready e; |
242 | + throw e; |
243 | + }; |
244 | +}; |
245 | + |
246 | +template <class T, class queue_t> |
247 | +void abs_queue<T,queue_t>::shutdown() |
248 | +{ |
249 | + try |
250 | + { |
251 | + std::unique_lock<std::mutex> lock(mylock); |
252 | + ready = false; |
253 | + while (buffer.size()) { buffer.pop(); } |
254 | + signal.notify_all(); |
255 | + } |
256 | + catch (...) {} |
257 | +} |
258 | + |
259 | +template <class T, class queue_t> |
260 | +int abs_queue<T,queue_t>::size() |
261 | +{ |
262 | + std::unique_lock<std::mutex> lock(mylock); |
263 | + return buffer.size(); |
264 | +}; |
265 | + |
266 | +template <class T, class queue_t> |
267 | +void abs_queue<T,queue_t>::resize(int newsize) |
268 | +{ |
269 | + std::unique_lock<std::mutex> lock(mylock); |
270 | + buffer.set_capacity(newsize); |
271 | +}; |
272 | + |
273 | +template <class T, class queue_t> |
274 | +void abs_queue<T,queue_t>::clear() |
275 | +{ |
276 | + std::unique_lock<std::mutex> lock(mylock); |
277 | + while (buffer.size()) buffer.pop(); |
278 | +}; |
279 | + |
280 | +} // namespace nrtb |
281 | + |
282 | +#endif //nrtb_abs_queue_h// |
283 | |
284 | === added file 'cpp/common/abs_queue/abs_queue_test.cpp' |
285 | --- cpp/common/abs_queue/abs_queue_test.cpp 1970-01-01 00:00:00 +0000 |
286 | +++ cpp/common/abs_queue/abs_queue_test.cpp 2013-08-09 21:47:12 +0000 |
287 | @@ -0,0 +1,120 @@ |
288 | +/*********************************************** |
289 | + This file is part of the NRTB project (https://*launchpad.net/nrtb). |
290 | + |
291 | + NRTB is free software: you can redistribute it and/or modify |
292 | + it under the terms of the GNU General Public License as published by |
293 | + the Free Software Foundation, either version 3 of the License, or |
294 | + (at your option) any later version. |
295 | + |
296 | + NRTB is distributed in the hope that it will be useful, |
297 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
298 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
299 | + GNU General Public License for more details. |
300 | + |
301 | + You should have received a copy of the GNU General Public License |
302 | + along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
303 | + |
304 | + **********************************************/ |
305 | + |
306 | +#include <unistd.h> // included for usleep() |
307 | +#include <string> |
308 | +#include <iostream> |
309 | +#include "abs_queue.h" |
310 | +#include <memory> |
311 | +#include <atomic> |
312 | +#include <future> |
313 | +#include <queue> |
314 | + |
315 | +using namespace nrtb; |
316 | +using namespace std; |
317 | + |
318 | +typedef abs_queue<int,std::queue<int>> test_queue; |
319 | +typedef shared_ptr<test_queue> queue_p; |
320 | + |
321 | +int consumer_task(string name, queue_p input) |
322 | +{ |
323 | + bool ready {true}; |
324 | + int count {0}; |
325 | + try |
326 | + { |
327 | + while (ready) |
328 | + { |
329 | + int num = input->pop(); |
330 | + count++; |
331 | + usleep(1); |
332 | + } |
333 | + } |
334 | + catch (...) |
335 | + { |
336 | + // exit if we get any exception. |
337 | + ready = false; |
338 | + }; |
339 | + return count; |
340 | +}; |
341 | + |
342 | +int main() |
343 | +{ |
344 | + cout << "***** abs_queue unit test ******" << endl; |
345 | + /************************************************ |
346 | + * Load queue and then cook it down... |
347 | + ***********************************************/ |
348 | + // make and load a queue |
349 | + queue_p q1(new test_queue()); |
350 | + for (int i=0; i<100; i++) |
351 | + { |
352 | + q1->push(i); |
353 | + }; |
354 | + // the queue should be loaded with 0-99 |
355 | + // attach a thread and process it. |
356 | + auto t1 = async(launch::async,consumer_task,"task 1",q1); |
357 | + while (q1->size()) usleep(100); |
358 | + cout << "cp 1 " |
359 | + << q1->in_count << ":" |
360 | + << q1->out_count << endl; |
361 | + /************************************************ |
362 | + * now that the preload is exhasted, shove items |
363 | + * in one at a time to make sure each is picked |
364 | + * up correctly. |
365 | + ***********************************************/ |
366 | + for (int i=200; i<225; i++) |
367 | + { |
368 | + q1->push(i); |
369 | + usleep(100); |
370 | + }; |
371 | + cout << "cp 2 " |
372 | + << q1->in_count << ":" |
373 | + << q1->out_count << endl; |
374 | + /************************************************ |
375 | + * Last check; attach a second thread to the queue |
376 | + * and make sure both are servicing it. |
377 | + ***********************************************/ |
378 | + auto t2 = async(launch::async,consumer_task,"task 2",q1); |
379 | + for (int i=300; i<325; i++) |
380 | + { |
381 | + q1->push(i); |
382 | + }; |
383 | + while (q1->size()) usleep(100); |
384 | + // shut it all down |
385 | + q1->shutdown(); |
386 | + // important numbers |
387 | + int t1_count = t1.get(); |
388 | + int t2_count = t2.get(); |
389 | + int q1_in = q1->in_count; |
390 | + int q1_out = q1->out_count; |
391 | + // release the queues. |
392 | + q1.reset(); |
393 | + // do some reporting. |
394 | + cout << "cp 3 " |
395 | + << q1_in << ":" << q1_out |
396 | + << " t1=" << t1_count |
397 | + << " t2=" << t2_count |
398 | + << endl; |
399 | + bool passed = (q1_in == q1_out) |
400 | + and (q1_out == (t1_count + t2_count)); |
401 | + cout << "***** abs_queue TEST " |
402 | + << (passed ? "PASSED" : "FAILED") |
403 | + << " ******" << endl; |
404 | + // inverted logic needed because 0 is good for |
405 | + // return codes. |
406 | + return !passed; |
407 | +}; |
408 | \ No newline at end of file |
409 | |
410 | === modified file 'cpp/common/circular_queue/Makefile' |
411 | --- obsolete/Cpp/common/circular_queue/Makefile 2012-04-06 12:10:36 +0000 |
412 | +++ cpp/common/circular_queue/Makefile 2013-08-09 21:47:12 +0000 |
413 | @@ -16,6 +16,8 @@ |
414 | # |
415 | #*********************************************** |
416 | |
417 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
418 | + |
419 | lib: circular_queue_test |
420 | @./circular_queue_test |
421 | @cp -v circular_queue.h ../include |
422 | @@ -23,8 +25,8 @@ |
423 | |
424 | circular_queue_test: circular_queue.h circular_queue_test.cpp |
425 | @rm -f circular_queue_test |
426 | - g++ -c circular_queue_test.cpp -I../include -std=gnu++0x |
427 | - g++ -o circular_queue_test circular_queue_test.o ../obj/common.o ../obj/base_thread.o -lpthread -std=gnu++0x |
428 | + g++ -c circular_queue_test.cpp -I../include ${switches} |
429 | + g++ -o circular_queue_test circular_queue_test.o -lpthread ${switches} |
430 | |
431 | clean: |
432 | @rm -rvf *.o circular_queue_test ../include/circular_queue.h *.log ../obj/circular_queue.o |
433 | |
434 | === modified file 'cpp/common/circular_queue/circular_queue.h' |
435 | --- obsolete/Cpp/common/circular_queue/circular_queue.h 2011-10-06 20:09:07 +0000 |
436 | +++ cpp/common/circular_queue/circular_queue.h 2013-08-09 21:47:12 +0000 |
437 | @@ -20,18 +20,31 @@ |
438 | #define nrtb_circular_queue_h |
439 | |
440 | #include <iostream> |
441 | -#include <base_thread.h> |
442 | #include <boost/circular_buffer.hpp> |
443 | +#include <atomic> |
444 | +#include <mutex> |
445 | +#include <condition_variable> |
446 | +#include <common.h> |
447 | +#include <abs_queue.h> |
448 | |
449 | namespace nrtb |
450 | { |
451 | + |
452 | +// specialize boost::circular_buffer to act like a queue. |
453 | +template <class T> |
454 | +class base_cq : public boost::circular_buffer<T> |
455 | +{ |
456 | +public: |
457 | + void push(T elem) { this->push_back(elem); }; |
458 | + void pop() { this->pop_front(); }; |
459 | +}; |
460 | |
461 | /******************************************************** |
462 | * The circular_queue template is designed for use with |
463 | * the classic producer/consumer thread management model. |
464 | * The producer uses circular_queue::push() to put items |
465 | * in the queue as they become available, and the consumer |
466 | - * thread calls circular_queue::park() when it is ready |
467 | + * thread calls circular_queue::pop() when it is ready |
468 | * for the next item to work. |
469 | * |
470 | * Common uses would be for buffering outgoing or incomming |
471 | @@ -41,132 +54,14 @@ |
472 | * passing data to another set of threads. |
473 | ********************************************************/ |
474 | template <class T> |
475 | -class circular_queue |
476 | -{ |
477 | -public: |
478 | - class queue_not_ready: public base_exception {}; |
479 | - |
480 | - /********************************************* |
481 | - * creates the queue with the specified |
482 | - * number of elements. All memory is allocated |
483 | - * at construction to minimize delays at runtime. |
484 | - *********************************************/ |
485 | - circular_queue(int size); |
486 | - |
487 | - /********************************************* |
488 | - * releases all items in the queue |
489 | - *********************************************/ |
490 | - virtual ~circular_queue(); |
491 | - |
492 | - /********************************************* |
493 | - * Puts an item in the queue. |
494 | - *********************************************/ |
495 | - void push(T item); |
496 | - |
497 | - /********************************************* |
498 | - * Pops the next item off the queue, blocking |
499 | - * if needed until an item becomes available. |
500 | - *********************************************/ |
501 | - T pop(); |
502 | - |
503 | - /********************************************* |
504 | - * puts the queue in shutdown mode. |
505 | - *********************************************/ |
506 | - void shutdown(); |
507 | - |
508 | - // returns the number of items in the queue |
509 | - int size(); |
510 | - // resizes the buffer, may cause data loss |
511 | - void resize(int newsize); |
512 | - // clears the buffer, data will be discarded. |
513 | - void clear(); |
514 | - |
515 | -protected: |
516 | - |
517 | - boost::circular_buffer<T> buffer; |
518 | - cond_variable buffer_lock; |
519 | - bool ready; |
520 | -}; |
521 | - |
522 | -template <class T> |
523 | -circular_queue<T>::circular_queue(int size) |
524 | -{ |
525 | - buffer.set_capacity(size); |
526 | - ready = true; |
527 | -}; |
528 | - |
529 | -// TODO: needed ... a queue stop method. |
530 | - |
531 | -template <class T> |
532 | -circular_queue<T>::~circular_queue() |
533 | -{ |
534 | -}; |
535 | - |
536 | -template <class T> |
537 | -void circular_queue<T>::push(T item) |
538 | -{ |
539 | - if (ready) |
540 | - { |
541 | - scope_lock lock(buffer_lock); |
542 | - buffer.push_back(item); |
543 | - buffer_lock.signal(); |
544 | - } |
545 | - else |
546 | - { |
547 | - queue_not_ready e; |
548 | - throw e; |
549 | - } |
550 | -}; |
551 | - |
552 | -template <class T> |
553 | -T circular_queue<T>::pop() |
554 | -{ |
555 | - scope_lock lock(buffer_lock); |
556 | - while (buffer.empty() && ready) |
557 | - buffer_lock.wait(); |
558 | - if (!ready) |
559 | - { |
560 | - queue_not_ready e; |
561 | - throw e; |
562 | - }; |
563 | - T returnme = buffer.front(); |
564 | - buffer.pop_front(); |
565 | - return returnme; |
566 | -}; |
567 | - |
568 | -template <class T> |
569 | -void circular_queue<T>::shutdown() |
570 | -{ |
571 | - try |
572 | - { |
573 | - scope_lock lock(buffer_lock); |
574 | - ready = false; |
575 | - buffer_lock.broadcast_signal(); |
576 | - buffer.clear(); |
577 | - } |
578 | - catch (...) {} |
579 | -} |
580 | - |
581 | - |
582 | -template <class T> |
583 | -int circular_queue<T>::size() |
584 | -{ |
585 | - scope_lock lock(buffer_lock); |
586 | - return buffer.size(); |
587 | -}; |
588 | - |
589 | -template <class T> |
590 | -void circular_queue<T>::resize(int newsize) |
591 | -{ |
592 | - scope_lock lock(buffer_lock); |
593 | - buffer.set_capacity(newsize); |
594 | -}; |
595 | - |
596 | -template <class T> |
597 | -void circular_queue<T>::clear() |
598 | -{ |
599 | - scope_lock lock(buffer_lock); |
600 | - buffer.clear(); |
601 | +class circular_queue : public abs_queue<T, base_cq<T>> |
602 | +{ |
603 | +public: |
604 | + // convienence constructor because a 0 size circular_queue is useless. |
605 | + circular_queue(int size=10) : abs_queue<T, base_cq<T>>() |
606 | + { |
607 | + this->resize(size); |
608 | + }; |
609 | }; |
610 | |
611 | } // namespace nrtb |
612 | |
613 | === modified file 'cpp/common/circular_queue/circular_queue_test.cpp' |
614 | --- obsolete/Cpp/common/circular_queue/circular_queue_test.cpp 2011-10-06 20:09:07 +0000 |
615 | +++ cpp/common/circular_queue/circular_queue_test.cpp 2013-08-09 21:47:12 +0000 |
616 | @@ -18,78 +18,41 @@ |
617 | |
618 | #include <string> |
619 | #include <iostream> |
620 | +#include <unistd.h> |
621 | #include "circular_queue.h" |
622 | -#include <boost/shared_ptr.hpp> |
623 | +#include <memory> |
624 | +#include <future> |
625 | |
626 | using namespace nrtb; |
627 | using namespace std; |
628 | |
629 | typedef circular_queue<int> test_queue; |
630 | -typedef boost::shared_ptr<test_queue> queue_p; |
631 | +typedef std::shared_ptr<test_queue> queue_p; |
632 | |
633 | -class consumer_task: public thread |
634 | +int consumer_task(string name, queue_p input) |
635 | { |
636 | -public: |
637 | - |
638 | - consumer_task(string n, queue_p buffer) |
639 | - { |
640 | - name = n; |
641 | - input = buffer; |
642 | - count = 0; |
643 | - }; |
644 | - |
645 | - ~consumer_task() |
646 | - { |
647 | - cout << ">> in " << name << "::~consumer_task()" << endl; |
648 | - try |
649 | - { |
650 | - this->thread::~thread(); |
651 | - input.reset(); |
652 | - } |
653 | - catch (...) {}; |
654 | - cout << "<< leaving " << name << "::~consumer_task()" << endl; |
655 | - }; |
656 | - |
657 | - int get_count() { return count; }; |
658 | - |
659 | - void run() |
660 | - { |
661 | - try |
662 | - { |
663 | - while (true) |
664 | - { |
665 | - int num = input->pop(); |
666 | - { |
667 | - static mutex console; |
668 | - scope_lock lock(console); |
669 | - cout << name << " picked up " << num |
670 | - << endl; |
671 | - }; |
672 | - count++; |
673 | - lastnum = num; |
674 | - yield(); |
675 | - } |
676 | - } |
677 | - catch (...) {}; |
678 | - }; |
679 | - |
680 | -protected: |
681 | - // link to the feed queue |
682 | - queue_p input; |
683 | - // a name to report |
684 | - string name; |
685 | - // number of items processed |
686 | - int count; |
687 | - // last number caught |
688 | - int lastnum; |
689 | + bool ready {true}; |
690 | + int count {0}; |
691 | + try |
692 | + { |
693 | + while (ready) |
694 | + { |
695 | + int num = input->pop(); |
696 | + count++; |
697 | + usleep(1); |
698 | + } |
699 | + } |
700 | + catch (...) |
701 | + { |
702 | + // exit on any exception |
703 | + ready = false; |
704 | + }; |
705 | + return count; |
706 | }; |
707 | |
708 | -typedef boost::shared_ptr<consumer_task> task_p; |
709 | - |
710 | - |
711 | int main() |
712 | { |
713 | - int er_count = 0; |
714 | + cout << "***** circular_queue unit test *****" << endl; |
715 | /************************************************ |
716 | * Load queue and then cook it down... |
717 | ***********************************************/ |
718 | @@ -101,10 +64,11 @@ |
719 | }; |
720 | // the queue should be loaded with 50-99 |
721 | // attach a thread and process it. |
722 | - task_p p1(new consumer_task("task 1",q1)); |
723 | - p1->start(); |
724 | + auto t1 = async(launch::async,consumer_task,"task 1",q1); |
725 | while (q1->size()) usleep(100); |
726 | - cout << "cp 1 " << p1->get_count() << endl; |
727 | + cout << "cp 1 " |
728 | + << q1->in_count << ":" |
729 | + << q1->out_count << endl; |
730 | /************************************************ |
731 | * now that the preload is exhasted, shove items |
732 | * in one at a time to make sure each is picked |
733 | @@ -112,40 +76,42 @@ |
734 | ***********************************************/ |
735 | for (int i=200; i<225; i++) |
736 | { |
737 | - q1->push(i); |
738 | - usleep(100); |
739 | + q1->push(i); |
740 | + usleep(100); |
741 | }; |
742 | - cout << "cp 2 " << p1->get_count() << endl; |
743 | + cout << "cp 2 " |
744 | + << q1->in_count << ":" |
745 | + << q1->out_count << endl; |
746 | /************************************************ |
747 | * Last check; attach a second thread to the queue |
748 | * and make sure both are servicing it. |
749 | ***********************************************/ |
750 | - task_p p2(new consumer_task("task 2",q1)); |
751 | - p2->start(); |
752 | + auto t2 = async(launch::async,consumer_task,"task 2",q1); |
753 | for (int i=300; i<325; i++) |
754 | { |
755 | - q1->push(i); |
756 | + q1->push(i); |
757 | }; |
758 | while (q1->size()) usleep(100); |
759 | // shut it all down |
760 | q1->shutdown(); |
761 | - p1->join(); |
762 | - p2->join(); |
763 | // important numbers |
764 | - int tot_items = p1->get_count() + p2->get_count(); |
765 | - int p1_items = p1->get_count() - 75; |
766 | - int p2_items = p2->get_count(); |
767 | + int q1_in = q1->in_count; |
768 | + int q1_out = q1->out_count; |
769 | + int t1_items = t1.get(); |
770 | + int t2_items = t2.get(); |
771 | // release she threads and queues. |
772 | - p1.reset(); |
773 | - p2.reset(); |
774 | q1.reset(); |
775 | // do some reporting. |
776 | cout << "cp 3 " |
777 | - << tot_items |
778 | - << " [75 + (" << p1_items |
779 | - << " + " << p2_items |
780 | - << ")]" << endl; |
781 | - bool passed = (tot_items == 100); |
782 | + << q1_in << ":" << q1_out |
783 | + << " t1=" << t1_items |
784 | + << " t2=" << t2_items |
785 | + << endl; |
786 | + bool passed = (q1_in - 50 == q1_out) |
787 | + and (q1_out == (t1_items + t2_items)); |
788 | + cout << "***** circular_queue TEST " |
789 | + << (passed ? "PASSED" : "FAILED") |
790 | + << " ******" << endl; |
791 | // inverted logic needed because 0 is good for |
792 | // return codes. |
793 | return !passed; |
794 | |
795 | === modified file 'cpp/common/common_rl/Makefile' |
796 | --- obsolete/Cpp/common/common_rl/Makefile 2012-04-06 12:16:10 +0000 |
797 | +++ cpp/common/common_rl/Makefile 2013-08-09 21:47:12 +0000 |
798 | @@ -16,6 +16,9 @@ |
799 | # |
800 | #*********************************************** |
801 | |
802 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
803 | + |
804 | + |
805 | lib: common_rl_test |
806 | @./common_rl_test |
807 | @cp -v common.h ../include |
808 | @@ -24,12 +27,12 @@ |
809 | |
810 | common.o: common.h common.cpp Makefile |
811 | @rm -f common.o |
812 | - g++ -c -O3 common.cpp -std=gnu++0x |
813 | + g++ -c -O3 common.cpp ${switches} |
814 | |
815 | common_rl_test: common.o common_rl_test.cpp |
816 | @rm -f common_rl_test |
817 | - g++ -c common_rl_test.cpp -std=gnu++0x |
818 | - g++ -o common_rl_test common_rl_test.o common.o -std=gnu++0x |
819 | + g++ -c common_rl_test.cpp ${switches} |
820 | + g++ -o common_rl_test common_rl_test.o common.o ${switches} |
821 | |
822 | clean: |
823 | @rm -rvf *.o ../include/common.h ../obj/common.o common_rl_test |
824 | |
825 | === modified file 'cpp/common/common_rl/common.cpp' |
826 | --- obsolete/Cpp/common/common_rl/common.cpp 2010-12-25 22:44:22 +0000 |
827 | +++ cpp/common/common_rl/common.cpp 2013-08-09 21:47:12 +0000 |
828 | @@ -19,7 +19,6 @@ |
829 | #include <stdlib.h> |
830 | #include <iostream> |
831 | #include <math.h> |
832 | -#include <time.h> |
833 | #include "common.h" |
834 | |
835 | using namespace std; |
836 | @@ -27,247 +26,224 @@ |
837 | namespace nrtb |
838 | { |
839 | |
840 | -base_exception::base_exception() |
841 | -{ |
842 | - ctime = time(NULL); |
843 | -}; |
844 | - |
845 | -base_exception::base_exception(const string & text) |
846 | -{ |
847 | - ctime = time(NULL); |
848 | - _text = text; |
849 | -}; |
850 | - |
851 | -void base_exception::store(const string & s) |
852 | -{ |
853 | - _text = s; |
854 | -}; |
855 | - |
856 | -string base_exception::comment() |
857 | -{ |
858 | - return _text; |
859 | -}; |
860 | - |
861 | -unsigned long int base_exception::creation_time() |
862 | -{ |
863 | - return ctime; |
864 | -}; |
865 | - |
866 | const string __ricks_handy_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
867 | const string __ricks_handy_lower = "abcdefghijklmnopqrstuvwxyz"; |
868 | |
869 | -string changecase(const string &s,const string &upper, const string &lower) |
870 | +string changecase(const string &s,const string &upper, |
871 | + const string &lower) |
872 | { |
873 | - try |
874 | - { |
875 | - string returnme = ""; |
876 | - for (int i = 0; i < s.size(); i++) |
877 | - { |
878 | - unsigned long int loc = lower.find(s[i]); |
879 | - if (loc == string::npos) |
880 | - { |
881 | - returnme += s[i]; |
882 | - } |
883 | - else |
884 | - { |
885 | - returnme += upper[loc]; |
886 | - }; |
887 | - }; |
888 | - return returnme; |
889 | - } |
890 | - catch (...) |
891 | - { |
892 | - throw translate_exception(); |
893 | - }; |
894 | + try |
895 | + { |
896 | + string returnme = ""; |
897 | + for (int i = 0; i < s.size(); i++) |
898 | + { |
899 | + unsigned long int loc = lower.find(s[i]); |
900 | + if (loc == string::npos) |
901 | + { |
902 | + returnme += s[i]; |
903 | + } |
904 | + else |
905 | + { |
906 | + returnme += upper[loc]; |
907 | + }; |
908 | + }; |
909 | + return returnme; |
910 | + } |
911 | + catch (...) |
912 | + { |
913 | + throw translate_exception(); |
914 | + }; |
915 | }; |
916 | |
917 | string upcase(const string &s) |
918 | { |
919 | - return changecase(s,__ricks_handy_upper,__ricks_handy_lower); |
920 | + return changecase(s,__ricks_handy_upper,__ricks_handy_lower); |
921 | }; |
922 | |
923 | string downcase(const string &s) |
924 | { |
925 | - return changecase(s,__ricks_handy_lower,__ricks_handy_upper); |
926 | + return changecase(s,__ricks_handy_lower,__ricks_handy_upper); |
927 | }; |
928 | |
929 | |
930 | const string __ricks_handy_hexits = "0123456789ABCDEF"; |
931 | |
932 | -string gsub(const string & target, const string & findme, const string & putme) |
933 | +string gsub(const string & target, const string & findme, |
934 | + const string & putme) |
935 | { |
936 | - // error checking |
937 | - if (findme.empty() || target.empty()) |
938 | - { |
939 | - throw gsub_exception(); |
940 | - }; |
941 | - string returnme = ""; |
942 | - unsigned long int okay_through = 0; |
943 | - unsigned long int step = findme.length(); |
944 | - unsigned long int where = target.find(findme,okay_through); |
945 | - while (where != string::npos) |
946 | - { |
947 | - returnme += target.substr(okay_through,where-okay_through) + putme; |
948 | - okay_through = where + step; |
949 | - where = target.find(findme,okay_through); |
950 | - }; |
951 | - returnme += target.substr(okay_through); |
952 | - return returnme; |
953 | + // error checking |
954 | + if (findme.empty() || target.empty()) |
955 | + { |
956 | + throw gsub_exception(); |
957 | + }; |
958 | + string returnme = ""; |
959 | + unsigned long int okay_through = 0; |
960 | + unsigned long int step = findme.length(); |
961 | + unsigned long int where = target.find(findme,okay_through); |
962 | + while (where != string::npos) |
963 | + { |
964 | + returnme += target.substr(okay_through,where-okay_through) + putme; |
965 | + okay_through = where + step; |
966 | + where = target.find(findme,okay_through); |
967 | + }; |
968 | + returnme += target.substr(okay_through); |
969 | + return returnme; |
970 | }; |
971 | |
972 | strlist split(const string & source, const char token) |
973 | { |
974 | - strlist returnme; |
975 | - returnme.clear(); |
976 | - if (source.size() > 0) |
977 | - { |
978 | - unsigned long int loc; |
979 | - unsigned long int processed = 0; |
980 | - try |
981 | - { |
982 | - loc = source.find(token,processed); |
983 | - while (loc != string::npos) |
984 | - { |
985 | - returnme.push_back(source.substr(processed,loc-processed)); |
986 | - processed = loc + 1; |
987 | - loc = source.find(token,processed); |
988 | - } |
989 | - returnme.push_back(source.substr(processed)); |
990 | - } |
991 | - catch (...) |
992 | - { |
993 | - throw split_exception(); |
994 | - }; |
995 | - }; |
996 | - return returnme; |
997 | + strlist returnme; |
998 | + returnme.clear(); |
999 | + if (source.size() > 0) |
1000 | + { |
1001 | + unsigned long int loc; |
1002 | + unsigned long int processed = 0; |
1003 | + try |
1004 | + { |
1005 | + loc = source.find(token,processed); |
1006 | + while (loc != string::npos) |
1007 | + { |
1008 | + returnme.push_back(source.substr(processed,loc-processed)); |
1009 | + processed = loc + 1; |
1010 | + loc = source.find(token,processed); |
1011 | + } |
1012 | + returnme.push_back(source.substr(processed)); |
1013 | + } |
1014 | + catch (...) |
1015 | + { |
1016 | + throw split_exception(); |
1017 | + }; |
1018 | + }; |
1019 | + return returnme; |
1020 | }; |
1021 | |
1022 | string trim(std::string s) |
1023 | { |
1024 | - const string ws = "\t\n "; |
1025 | - unsigned long int where = s.find_first_not_of(ws); |
1026 | - if (where != string::npos) |
1027 | - { |
1028 | - s.erase(0,where); |
1029 | - }; |
1030 | - where = s.find_last_not_of(ws); |
1031 | - if (where != string::npos) |
1032 | - { |
1033 | - s.erase(where+1); |
1034 | - }; |
1035 | - return s; |
1036 | + const string ws = "\t\n "; |
1037 | + unsigned long int where = s.find_first_not_of(ws); |
1038 | + if (where != string::npos) |
1039 | + { |
1040 | + s.erase(0,where); |
1041 | + }; |
1042 | + where = s.find_last_not_of(ws); |
1043 | + if (where != string::npos) |
1044 | + { |
1045 | + s.erase(where+1); |
1046 | + }; |
1047 | + return s; |
1048 | }; |
1049 | |
1050 | string mconvert(const string &s) |
1051 | { |
1052 | - /* This function is designed to escape strings destined for |
1053 | - * use in SQL queries and the like. Specifically, the following |
1054 | - * is done to the string passed in: |
1055 | - * 1. "\" is replaced with "\\" |
1056 | - * 2. "'" is replaced with "\'" |
1057 | - * 3. """ (double quote) is replaced with "\"" |
1058 | - * 4. 0x00 is replaced with "\"+0x00. |
1059 | - */ |
1060 | - string returnme = ""; |
1061 | - if (s.length() > 0) |
1062 | - { |
1063 | - returnme = gsub(s,"\\","\\\\"); |
1064 | - returnme = gsub(returnme,"'", "\\'"); |
1065 | - returnme = gsub(returnme,"\"","\\\""); |
1066 | - // special handling is required to make strings including |
1067 | - // 0x00; this is the kludge I found to work at 2200 tonight. |
1068 | - string findme = " "; findme[0] = 0; |
1069 | - returnme = gsub(returnme,findme,"\\0"); |
1070 | - }; |
1071 | - return returnme; |
1072 | + /* This function is designed to escape strings destined for |
1073 | + * use in SQL queries and the like. Specifically, the following |
1074 | + * is done to the string passed in: |
1075 | + * 1. "\" is replaced with "\\" |
1076 | + * 2. "'" is replaced with "\'" |
1077 | + * 3. """ (double quote) is replaced with "\"" |
1078 | + * 4. 0x00 is replaced with "\"+0x00. |
1079 | + */ |
1080 | + string returnme = ""; |
1081 | + if (s.length() > 0) |
1082 | + { |
1083 | + returnme = gsub(s,"\\","\\\\"); |
1084 | + returnme = gsub(returnme,"'", "\\'"); |
1085 | + returnme = gsub(returnme,"\"","\\\""); |
1086 | + // special handling is required to make strings including |
1087 | + // 0x00; this is the kludge I found to work at 2200 tonight. |
1088 | + string findme = " "; findme[0] = 0; |
1089 | + returnme = gsub(returnme,findme,"\\0"); |
1090 | + }; |
1091 | + return returnme; |
1092 | }; |
1093 | |
1094 | string dateflip(string date, const string & sep) |
1095 | { |
1096 | - string out; |
1097 | - try |
1098 | - { |
1099 | - strlist temp = split(date,'-'); |
1100 | - out = temp[1]+ sep + temp[2] + sep + temp[0]; |
1101 | - } |
1102 | - catch (...) |
1103 | - { |
1104 | - throw dateflip_exception(); |
1105 | - }; |
1106 | - return out; |
1107 | + string out; |
1108 | + try |
1109 | + { |
1110 | + strlist temp = split(date,'-'); |
1111 | + out = temp[1]+ sep + temp[2] + sep + temp[0]; |
1112 | + } |
1113 | + catch (...) |
1114 | + { |
1115 | + throw dateflip_exception(); |
1116 | + }; |
1117 | + return out; |
1118 | }; // string dateflip |
1119 | |
1120 | string http_hextochar(string s) |
1121 | { |
1122 | - try |
1123 | - { |
1124 | - s = upcase(s); |
1125 | - unsigned char v = (16 * __ricks_handy_hexits.find(s[0])) |
1126 | - + __ricks_handy_hexits.find(s[1]); |
1127 | - return s = v; |
1128 | - } |
1129 | - catch (...) |
1130 | - { |
1131 | - throw hextrans_exception(); |
1132 | - }; |
1133 | + try |
1134 | + { |
1135 | + s = upcase(s); |
1136 | + unsigned char v = (16 * __ricks_handy_hexits.find(s[0])) |
1137 | + + __ricks_handy_hexits.find(s[1]); |
1138 | + return s = v; |
1139 | + } |
1140 | + catch (...) |
1141 | + { |
1142 | + throw hextrans_exception(); |
1143 | + }; |
1144 | }; // string hextochar |
1145 | |
1146 | string http_chartohex(const string &s) |
1147 | { |
1148 | - string out; |
1149 | - try |
1150 | - { |
1151 | - for (long int i=0; i < s.length() ; i++ ) { |
1152 | - unsigned char v = s[i]; |
1153 | - div_t hexval = div(v,16); |
1154 | - out += __ricks_handy_hexits[hexval.quot]; |
1155 | - out += __ricks_handy_hexits[hexval.rem]; |
1156 | - }; /* endfor */ |
1157 | - } |
1158 | - catch (...) |
1159 | - { |
1160 | - throw hextrans_exception(); |
1161 | - }; |
1162 | - return out; |
1163 | + string out; |
1164 | + try |
1165 | + { |
1166 | + for (long int i=0; i < s.length() ; i++ ) { |
1167 | + unsigned char v = s[i]; |
1168 | + div_t hexval = div(v,16); |
1169 | + out += __ricks_handy_hexits[hexval.quot]; |
1170 | + out += __ricks_handy_hexits[hexval.rem]; |
1171 | + }; /* endfor */ |
1172 | + } |
1173 | + catch (...) |
1174 | + { |
1175 | + throw hextrans_exception(); |
1176 | + }; |
1177 | + return out; |
1178 | };// string chartohex() |
1179 | |
1180 | string http_enhex(const string & s) |
1181 | { |
1182 | - string out; |
1183 | - try |
1184 | - { |
1185 | - for (long int i=0; i < s.length() ; i++ ) { |
1186 | - unsigned char v = s[i]; |
1187 | - div_t hexval = div(v,16); |
1188 | - out += "%"; |
1189 | - out += __ricks_handy_hexits[hexval.quot]; |
1190 | - out += __ricks_handy_hexits[hexval.rem]; |
1191 | - }; /* endfor */ |
1192 | - } |
1193 | - catch (...) |
1194 | - { |
1195 | - throw hextrans_exception(); |
1196 | - }; |
1197 | - return out; |
1198 | + string out; |
1199 | + try |
1200 | + { |
1201 | + for (long int i=0; i < s.length() ; i++ ) |
1202 | + { |
1203 | + unsigned char v = s[i]; |
1204 | + div_t hexval = div(v,16); |
1205 | + out += "%"; |
1206 | + out += __ricks_handy_hexits[hexval.quot]; |
1207 | + out += __ricks_handy_hexits[hexval.rem]; |
1208 | + }; /* endfor */ |
1209 | + } |
1210 | + catch (...) |
1211 | + { |
1212 | + throw hextrans_exception(); |
1213 | + }; |
1214 | + return out; |
1215 | }; // string enhex() |
1216 | |
1217 | string http_unhex(string s) |
1218 | { |
1219 | - try |
1220 | - { |
1221 | - while (s.find('%') != string::npos) |
1222 | - { |
1223 | - int where = s.find('%'); |
1224 | - string hexchar = s.substr(where+1,2); |
1225 | - s.erase(where,3); |
1226 | - s.insert(where,http_hextochar(hexchar)); |
1227 | - }; /* endwhile */ |
1228 | - } |
1229 | - catch (...) |
1230 | - { |
1231 | - throw hextrans_exception(); |
1232 | - }; |
1233 | - return s; |
1234 | + try |
1235 | + { |
1236 | + while (s.find('%') != string::npos) |
1237 | + { |
1238 | + int where = s.find('%'); |
1239 | + string hexchar = s.substr(where+1,2); |
1240 | + s.erase(where,3); |
1241 | + s.insert(where,http_hextochar(hexchar)); |
1242 | + }; /* endwhile */ |
1243 | + } |
1244 | + catch (...) |
1245 | + { |
1246 | + throw hextrans_exception(); |
1247 | + }; |
1248 | + return s; |
1249 | };// string unhex() |
1250 | |
1251 | |
1252 | |
1253 | === modified file 'cpp/common/common_rl/common.h' |
1254 | --- obsolete/Cpp/common/common_rl/common.h 2010-12-25 22:44:22 +0000 |
1255 | +++ cpp/common/common_rl/common.h 2013-08-09 21:47:12 +0000 |
1256 | @@ -20,10 +20,10 @@ |
1257 | #ifndef __ga_common_h |
1258 | #define __ga_common_h 1 |
1259 | |
1260 | -//#include <stream.h> |
1261 | #include <string> |
1262 | #include <map> |
1263 | #include <vector> |
1264 | +#include <chrono> |
1265 | |
1266 | namespace nrtb |
1267 | { |
1268 | @@ -39,40 +39,36 @@ |
1269 | ** get the time the exception was created and any text the thrower may have |
1270 | ** provided. |
1271 | **/ |
1272 | - class base_exception: public std::exception |
1273 | - { |
1274 | - protected: |
1275 | - unsigned long int ctime; |
1276 | - std::string _text; |
1277 | - public: |
1278 | - /** Default constructor. |
1279 | - ** |
1280 | - ** Creates an nrtb_exception recording it's creation time but without |
1281 | - ** a comment string. |
1282 | - **/ |
1283 | - base_exception(); |
1284 | - /** Constructs with a comment string. |
1285 | - ** |
1286 | - ** Creates an nrtb_exception recording it's creation time and storing the |
1287 | - ** provided string "text" for recall later via the comment method. |
1288 | - ** |
1289 | - ** This version takes an ISO standard C++ string. |
1290 | - **/ |
1291 | - base_exception(const std::string & text); |
1292 | - /// NOP virtual distructor for safe inheritance |
1293 | - virtual ~base_exception() throw() {}; |
1294 | - /** Stores a comment string. |
1295 | - **/ |
1296 | - void store(const std::string & s); |
1297 | - /** Returns the value stored at exception creation. |
1298 | - **/ |
1299 | - std::string comment(); |
1300 | - /** Returns the unix time the exception was created. |
1301 | - **/ |
1302 | - unsigned long int creation_time(); |
1303 | +class base_exception: public std::exception |
1304 | +{ |
1305 | +protected: |
1306 | + typedef std::chrono::high_resolution_clock myclock; |
1307 | + typedef std::chrono::high_resolution_clock::time_point mark; |
1308 | + typedef std::chrono::microseconds ms; |
1309 | + mark created {myclock::now()}; |
1310 | + std::string _text; |
1311 | + |
1312 | +public: |
1313 | + /// NOP virtual distructor for safe inheritance |
1314 | + virtual ~base_exception() throw() {}; |
1315 | + /** Stores a comment string. |
1316 | + **/ |
1317 | + void store(const std::string & s) { _text = s; }; |
1318 | + /** Returns the value stored at exception creation. |
1319 | + **/ |
1320 | + std::string comment() { return _text; }; |
1321 | + /** Returns the time the exception was created. |
1322 | + **/ |
1323 | + mark creation_time() { return created; }; |
1324 | + /** Returns the age of the exception |
1325 | + **/ |
1326 | + ms age_in_ms() |
1327 | + { |
1328 | + return std::chrono::duration_cast<ms>(myclock::now() - created); |
1329 | + }; |
1330 | }; |
1331 | |
1332 | -// Thrown by gsub() in cases of unexpected error. |
1333 | +// Thrown by gsub() in cases of unexpectaed error. |
1334 | class gsub_exception: public nrtb::base_exception {}; |
1335 | // Thrown by split() in cases of unexpected error. |
1336 | class split_exception: public nrtb::base_exception {}; |
1337 | |
1338 | === modified file 'cpp/common/common_rl/common_rl_test.cpp' |
1339 | --- obsolete/Cpp/common/common_rl/common_rl_test.cpp 2011-07-21 22:14:53 +0000 |
1340 | +++ cpp/common/common_rl/common_rl_test.cpp 2013-08-09 21:47:12 +0000 |
1341 | @@ -18,6 +18,7 @@ |
1342 | |
1343 | #include "common.h" |
1344 | #include <iostream> |
1345 | +#include <unistd.h> |
1346 | |
1347 | using namespace std; |
1348 | |
1349 | @@ -96,6 +97,23 @@ |
1350 | "nrtb::http_unhex()", |
1351 | nrtb::http_unhex("%4D%69%58%65%44%63%41%73%45") == tstr); |
1352 | |
1353 | + try |
1354 | + { |
1355 | + nrtb::base_exception e; |
1356 | + e.store("Test code"); |
1357 | + usleep(100); |
1358 | + throw e; |
1359 | + } |
1360 | + catch (nrtb::base_exception & e) |
1361 | + { |
1362 | + returnme += report_test( |
1363 | + "nrtb::base_exception::comment()", |
1364 | + e.comment() == "Test code"); |
1365 | + returnme += report_test( |
1366 | + "nrtb::base_exception::age_in_ms()", |
1367 | + e.age_in_ms().count() > 100 ); |
1368 | + }; |
1369 | + |
1370 | cout << "=== nrtb::common_rl unit test complete ===" << endl; |
1371 | return returnme; |
1372 | }; |
1373 | \ No newline at end of file |
1374 | |
1375 | === modified file 'cpp/common/confreader/Makefile' |
1376 | --- obsolete/Cpp/common/confreader/Makefile 2012-04-06 12:19:37 +0000 |
1377 | +++ cpp/common/confreader/Makefile 2013-08-09 21:47:12 +0000 |
1378 | @@ -16,6 +16,8 @@ |
1379 | # |
1380 | #*********************************************** |
1381 | |
1382 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
1383 | + |
1384 | lib: conftest |
1385 | @rm -f conf_test.log |
1386 | @./conftest test=1 test2-2 test2=71.837486 test3="jack danials" --doit |
1387 | @@ -26,12 +28,12 @@ |
1388 | |
1389 | confreader.o: confreader.h confreader.cpp Makefile |
1390 | @rm -f confreader.o |
1391 | - g++ -c confreader.cpp -I../include -std=gnu++0x |
1392 | + g++ -c confreader.cpp -I../include ${switches} |
1393 | |
1394 | conftest: confreader.o conftest.cpp |
1395 | @rm -f conftest |
1396 | - g++ -c conftest.cpp -I../include -std=gnu++0x |
1397 | - g++ -o conftest conftest.o confreader.o ../obj/common.o ../obj/log_setup.o ../obj/base_thread.o -lpthread -lPocoFoundation -lPocoUtil -std=gnu++0x |
1398 | + g++ -c conftest.cpp -I../include ${switches} |
1399 | + g++ -o conftest conftest.o confreader.o ../obj/common.o ../obj/logger.o -lpthread ${switches} |
1400 | |
1401 | clean: |
1402 | @rm -rvf *.o conftest ../include/confreader.h ../obj/confreader.o conf_test.log |
1403 | |
1404 | === modified file 'cpp/common/confreader/confreader.cpp' |
1405 | --- obsolete/Cpp/common/confreader/confreader.cpp 2011-08-13 15:06:08 +0000 |
1406 | +++ cpp/common/confreader/confreader.cpp 2013-08-09 21:47:12 +0000 |
1407 | @@ -21,206 +21,198 @@ |
1408 | #include "confreader.h" |
1409 | #include <fstream> |
1410 | #include <iostream> |
1411 | -#include <common.h> |
1412 | -#include "Poco/Logger.h" |
1413 | |
1414 | using namespace std; |
1415 | using namespace nrtb; |
1416 | |
1417 | -const std::string logname = "conf_reader"; |
1418 | - |
1419 | namespace nrtb |
1420 | { |
1421 | |
1422 | conf_reader::conf_reader() |
1423 | { |
1424 | - Poco::Logger& logger = Poco::Logger::get(logname); |
1425 | - logger.information("conf_reader instanciated."); |
1426 | + // nop constructor |
1427 | }; |
1428 | |
1429 | -conf_reader::~conf_reader() {}; |
1430 | +conf_reader::~conf_reader() |
1431 | +{ |
1432 | + // nop destructor |
1433 | +}; |
1434 | |
1435 | unsigned int conf_reader::read(const std::string & _filename, bool _clear) |
1436 | { |
1437 | - Poco::Logger& logger = Poco::Logger::get(logname); |
1438 | - logger.information("Reading from \"" + _filename + "\"."); |
1439 | - if (_filename != "") { filename = _filename; }; |
1440 | - if (filename != "") |
1441 | - { |
1442 | - try |
1443 | - { |
1444 | - ifstream cfile(filename.c_str()); |
1445 | - if (!cfile) throw base_exception(); |
1446 | - if (_clear) values.clear(); |
1447 | - // read the file line by line, ignoring comments. |
1448 | - char inbuff[16*1024]; |
1449 | - while (cfile) |
1450 | - { |
1451 | - cfile.getline(inbuff, 16*1024); |
1452 | - string in = inbuff; |
1453 | - // truncate at the start of a comment. |
1454 | - unsigned long int where = in.find("#"); |
1455 | - while (where != string::npos) |
1456 | - { |
1457 | - if (in[where-1] == '\\') |
1458 | - { |
1459 | - // comment char was escaped.. ignore. |
1460 | - where = in.find("#",where+1); |
1461 | - } |
1462 | - else |
1463 | - { |
1464 | - // truncate the string at this point. |
1465 | - in.erase(where); |
1466 | - where = string::npos; |
1467 | - }; |
1468 | - }; |
1469 | - // see if we can parse what's left. |
1470 | - in = trim(in); |
1471 | - unsigned long int split_point = in.find_first_of("\t "); |
1472 | - if (split_point != string::npos) |
1473 | - { |
1474 | - // okay.. get the fields. |
1475 | - pair arg; |
1476 | - arg.first = gsub(trim(in.substr(0,split_point)),"\\#","#"); |
1477 | - arg.second = gsub(trim(in.substr(split_point)),"\\#","#"); |
1478 | - // is this an include directive? |
1479 | - if (arg.first == "*INCLUDE") |
1480 | - { |
1481 | - read(arg.second,false); |
1482 | - } |
1483 | - else if (arg.first != "") |
1484 | - { |
1485 | - values.insert(arg); |
1486 | - }; |
1487 | - }; |
1488 | - }; |
1489 | - } |
1490 | - catch (...) |
1491 | - { |
1492 | - logger.warning("Problems reading configuration file \"" |
1493 | - + filename + "\"; data may be incomplete."); |
1494 | - } |
1495 | - }; |
1496 | - return values.size(); |
1497 | + if (_filename != "") { filename = _filename; }; |
1498 | + if (filename != "") |
1499 | + { |
1500 | + try |
1501 | + { |
1502 | + ifstream cfile(filename.c_str()); |
1503 | + if (!cfile) throw base_exception(); |
1504 | + if (_clear) values.clear(); |
1505 | + // read the file line by line, ignoring comments. |
1506 | + char inbuff[16*1024]; |
1507 | + while (cfile) |
1508 | + { |
1509 | + cfile.getline(inbuff, 16*1024); |
1510 | + string in = inbuff; |
1511 | + // truncate at the start of a comment. |
1512 | + unsigned long int where = in.find("#"); |
1513 | + while (where != string::npos) |
1514 | + { |
1515 | + if (in[where-1] == '\\') |
1516 | + { |
1517 | + // comment char was escaped.. ignore. |
1518 | + where = in.find("#",where+1); |
1519 | + } |
1520 | + else |
1521 | + { |
1522 | + // truncate the string at this point. |
1523 | + in.erase(where); |
1524 | + where = string::npos; |
1525 | + }; |
1526 | + }; |
1527 | + // see if we can parse what's left. |
1528 | + in = trim(in); |
1529 | + unsigned long int split_point = in.find_first_of("\t "); |
1530 | + if (split_point != string::npos) |
1531 | + { |
1532 | + // okay.. get the fields. |
1533 | + pair arg; |
1534 | + arg.first = gsub(trim(in.substr(0,split_point)),"\\#","#"); |
1535 | + arg.second = gsub(trim(in.substr(split_point)),"\\#","#"); |
1536 | + // is this an include directive? |
1537 | + if (arg.first == "*INCLUDE") |
1538 | + { |
1539 | + read(arg.second,false); |
1540 | + } |
1541 | + else if (arg.first != "") |
1542 | + { |
1543 | + values.insert(arg); |
1544 | + }; |
1545 | + }; |
1546 | + }; |
1547 | + } |
1548 | + catch (...) |
1549 | + { |
1550 | + cerr << "WARNING:Problems reading configuration file \"" |
1551 | + << filename << "\"; data may be incomplete."; |
1552 | + } |
1553 | + }; |
1554 | + return values.size(); |
1555 | }; |
1556 | |
1557 | unsigned int conf_reader::read(int argc, char * argv[], |
1558 | const string & _filename) |
1559 | { |
1560 | - Poco::Logger& logger = Poco::Logger::get(logname); |
1561 | - logger.information("Reading from command line."); |
1562 | - clear(); |
1563 | - filename = _filename; |
1564 | - value_list_type cvars; |
1565 | - // read values from the command line first. |
1566 | - for (int i = 0; i < argc; i++) |
1567 | - { |
1568 | - string instring = argv[i]; |
1569 | - if (i == 0) |
1570 | - { |
1571 | - instring = "__exec_name="+instring; |
1572 | - }; |
1573 | - strlist t = split(instring,'='); |
1574 | - if (t.size() > 0) |
1575 | - { |
1576 | - // build the new insert pair; |
1577 | - pair newval; |
1578 | - newval.first = t[0]; |
1579 | - // assemble the value |
1580 | - // (allows for including "=" in the argument) |
1581 | - for (unsigned int l = 1; l < t.size(); l++) |
1582 | - { |
1583 | - newval.second += t[l]; |
1584 | - if (l < (t.size() -1) ) |
1585 | - { |
1586 | - newval.second += "="; |
1587 | - }; |
1588 | - }; |
1589 | - // store this in the list |
1590 | - trim(newval.first); |
1591 | - trim(newval.second); |
1592 | - cvars.insert(newval); |
1593 | - // is this a config file name? |
1594 | - if (newval.first == "configfile") |
1595 | - { |
1596 | - filename = newval.second; |
1597 | - }; |
1598 | - }; |
1599 | - }; // read the command line arguments. |
1600 | - // read the file args if any. |
1601 | - read(filename,false); |
1602 | - // override the first instance of any value found in configs |
1603 | - // or insert as appropriate. |
1604 | - iterator c = cvars.begin(); |
1605 | - iterator e = cvars.end(); |
1606 | - while (c != e) |
1607 | - { |
1608 | - iterator here = values.find(c->first); |
1609 | - if (here != values.end()) |
1610 | - { |
1611 | - here->second = c->second; |
1612 | - } |
1613 | - else |
1614 | - { |
1615 | - values.insert(*c); |
1616 | - }; |
1617 | - c++; |
1618 | + clear(); |
1619 | + filename = _filename; |
1620 | + value_list_type cvars; |
1621 | + // read values from the command line first. |
1622 | + for (int i = 0; i < argc; i++) |
1623 | + { |
1624 | + string instring = argv[i]; |
1625 | + if (i == 0) |
1626 | + { |
1627 | + instring = "__exec_name="+instring; |
1628 | + }; |
1629 | + strlist t = split(instring,'='); |
1630 | + if (t.size() > 0) |
1631 | + { |
1632 | + // build the new insert pair; |
1633 | + pair newval; |
1634 | + newval.first = t[0]; |
1635 | + // assemble the value |
1636 | + // (allows for including "=" in the argument) |
1637 | + for (unsigned int l = 1; l < t.size(); l++) |
1638 | + { |
1639 | + newval.second += t[l]; |
1640 | + if (l < (t.size() -1) ) |
1641 | + { |
1642 | + newval.second += "="; |
1643 | }; |
1644 | - std::stringstream message; |
1645 | - message << "Read " << values.size() << " parameters."; |
1646 | - logger.information(message.str()); |
1647 | - return values.size(); |
1648 | + }; |
1649 | + // store this in the list |
1650 | + trim(newval.first); |
1651 | + trim(newval.second); |
1652 | + cvars.insert(newval); |
1653 | + // is this a config file name? |
1654 | + if (newval.first == "configfile") |
1655 | + { |
1656 | + filename = newval.second; |
1657 | + }; |
1658 | + }; |
1659 | + }; // read the command line arguments. |
1660 | + // read the file args if any. |
1661 | + read(filename,false); |
1662 | + // override the first instance of any value found in configs |
1663 | + // or insert as appropriate. |
1664 | + iterator c = cvars.begin(); |
1665 | + iterator e = cvars.end(); |
1666 | + while (c != e) |
1667 | + { |
1668 | + iterator here = values.find(c->first); |
1669 | + if (here != values.end()) |
1670 | + { |
1671 | + here->second = c->second; |
1672 | + } |
1673 | + else |
1674 | + { |
1675 | + values.insert(*c); |
1676 | + }; |
1677 | + c++; |
1678 | + }; |
1679 | + cout << "Read " << values.size() << " parameters."; |
1680 | + return values.size(); |
1681 | }; |
1682 | |
1683 | void conf_reader::clear() |
1684 | { |
1685 | - values.clear(); |
1686 | + values.clear(); |
1687 | }; |
1688 | |
1689 | conf_reader::iterator conf_reader::begin() |
1690 | { |
1691 | - return values.begin(); |
1692 | + return values.begin(); |
1693 | }; |
1694 | |
1695 | conf_reader::iterator conf_reader::end() |
1696 | { |
1697 | - return values.end(); |
1698 | + return values.end(); |
1699 | }; |
1700 | |
1701 | bool conf_reader::empty() |
1702 | { |
1703 | - return values.empty(); |
1704 | + return values.empty(); |
1705 | }; |
1706 | |
1707 | unsigned int conf_reader::size() |
1708 | { |
1709 | - return values.size(); |
1710 | + return values.size(); |
1711 | }; |
1712 | |
1713 | strlist conf_reader::all(const std::string & key) |
1714 | { |
1715 | - strlist returnme; |
1716 | - iterator current = values.find(key); |
1717 | - iterator e = values.end(); |
1718 | - while ((current != e) && (current->first == key)) |
1719 | - { |
1720 | - returnme.push_back(current->second); |
1721 | - current++; |
1722 | - }; |
1723 | - return returnme; |
1724 | + strlist returnme; |
1725 | + iterator current = values.find(key); |
1726 | + iterator e = values.end(); |
1727 | + while ((current != e) && (current->first == key)) |
1728 | + { |
1729 | + returnme.push_back(current->second); |
1730 | + current++; |
1731 | + }; |
1732 | + return returnme; |
1733 | }; |
1734 | |
1735 | string conf_reader::operator [] (const std::string & key) |
1736 | { |
1737 | - iterator res = values.find(key); |
1738 | - string returnme = ""; |
1739 | - if (res != values.end()) returnme = res->second; |
1740 | - return returnme; |
1741 | + iterator res = values.find(key); |
1742 | + string returnme = ""; |
1743 | + if (res != values.end()) returnme = res->second; |
1744 | + return returnme; |
1745 | }; |
1746 | |
1747 | bool conf_reader::exists(const std::string & key) |
1748 | { |
1749 | - return (values.find(key) != values.end()); |
1750 | + return (values.find(key) != values.end()); |
1751 | }; |
1752 | |
1753 | } // namespace nrtb |
1754 | |
1755 | === modified file 'cpp/common/confreader/confreader.h' |
1756 | --- obsolete/Cpp/common/confreader/confreader.h 2011-08-13 15:06:08 +0000 |
1757 | +++ cpp/common/confreader/confreader.h 2013-08-09 21:47:12 +0000 |
1758 | @@ -16,8 +16,8 @@ |
1759 | |
1760 | **********************************************/ |
1761 | |
1762 | -#ifndef ricklib_confreader_h |
1763 | -#define ricklib_confreader_h |
1764 | +#ifndef nrtb_confreader_h |
1765 | +#define nrtb_confreader_h |
1766 | |
1767 | #include <string.h> |
1768 | #include <map> |
1769 | @@ -25,13 +25,13 @@ |
1770 | #include <string> |
1771 | #include <fstream> |
1772 | #include <boost/lexical_cast.hpp> |
1773 | +#include <common.h> |
1774 | +#include <logger.h> |
1775 | #include <singleton.h> |
1776 | |
1777 | -namespace nrtb |
1778 | +namespace nrtb |
1779 | { |
1780 | |
1781 | -typedef std::vector<std::string> strlist; |
1782 | - |
1783 | /** Reads command line and configuration file information. |
1784 | ** |
1785 | ** For this NRTB implementation, this class is implemented as |
1786 | @@ -47,241 +47,242 @@ |
1787 | **/ |
1788 | class conf_reader |
1789 | { |
1790 | - private: |
1791 | - typedef std::multimap<std::string,std::string> value_list_type; |
1792 | - value_list_type values; |
1793 | - std::string filename; |
1794 | - protected: |
1795 | - /** Reads and parses a configuration file. |
1796 | - ** |
1797 | - ** Returns the number of values stored. |
1798 | - ** |
1799 | - ** The optional parameter _clear when true clears the currently |
1800 | - ** stored list of values. if false the new values read will be added |
1801 | - ** to the existing list. |
1802 | - ** |
1803 | - ** If the file named can not be processed completely, a warning |
1804 | - ** message is published to cerr. |
1805 | - ** |
1806 | - ** Configuration files are defined as follows. |
1807 | - ** |
1808 | - ** 1. Files are read line by line. No value can cross a newline |
1809 | - ** (and at least in this version) or include one. The good |
1810 | - ** news is that you are allowed up to 16k for each line. |
1811 | - ** |
1812 | - ** 2. values are specifed in name/value pairs, one per line, with |
1813 | - ** the name first, followed by whitespace, followed by the |
1814 | - ** value. Values may include whitespace. All leading and trailing |
1815 | - ** whitespace is removed from both the name and the value. |
1816 | - ** |
1817 | - ** 3. Comments start with a \# symbol; all text following a \# is |
1818 | - ** ignored. If you need to use \# in a name or value, escape |
1819 | - ** it with a backslash instead. |
1820 | - ** |
1821 | - ** 4. Duplicate names are allowed. |
1822 | - ** |
1823 | - ** 5. Names without values will be stored with "" as the value. |
1824 | - ** |
1825 | - ** 6. A configuration file may include another configuration file |
1826 | - ** automatically by the use of the "*INCLUDE" reserved name. |
1827 | - ** When this name is found, it's value is used as the name of |
1828 | - ** the new file to be read. |
1829 | - **/ |
1830 | - unsigned int read(const std::string & _filename = "", bool _clear=true); |
1831 | - public: |
1832 | - /// conf_reader iterator, points to a conf_reader::pair |
1833 | - typedef value_list_type::iterator iterator; |
1834 | - /// conf_reader::pair is a std::pair<string,string> |
1835 | - typedef std::pair<std::string,std::string> pair; |
1836 | - /** No argument constructor; actually calls read() without a filename. |
1837 | - **/ |
1838 | - conf_reader(); |
1839 | - /** NOP virtual destructor to allow safe inheritance. |
1840 | - **/ |
1841 | - virtual ~conf_reader(); |
1842 | - /** Reads and parses the command line and the provided file. |
1843 | - ** |
1844 | - ** Returns the number of values stored. argc and argv are, of |
1845 | - ** course the same names you used as arguments to main(). Therefore |
1846 | - ** you can easily read all command line and configuration file |
1847 | - ** values like this: |
1848 | - ** |
1849 | - ** int main(int argc, char* argv[]) |
1850 | - ** |
1851 | - ** { |
1852 | - ** |
1853 | - ** conf_reader config; |
1854 | - ** |
1855 | - ** config.read(argc,argv,"my_conf_file"); |
1856 | - ** |
1857 | - ** ... |
1858 | - ** |
1859 | - ** } |
1860 | - ** |
1861 | - ** See read(filename,_clear) for a discription of how configuration |
1862 | - ** files are structured and parsed. This method unconditionally |
1863 | - ** clears the existing value list before starting. For command line |
1864 | - ** arguments the following rules are true. |
1865 | - ** |
1866 | - ** 1. The executable name (argv[0]) is stored as a value with the |
1867 | - ** name "__exec_name". |
1868 | - ** |
1869 | - ** 2. Command line arguments of the form "name=value" are parsed |
1870 | - ** stored as named values. |
1871 | - ** |
1872 | - ** 3. All other command line arguments are stored as names with |
1873 | - ** value = "". |
1874 | - ** |
1875 | - ** 4. A command line argument of form "configfile=filename" will |
1876 | - ** override the filename supplied as an argument to this method. |
1877 | - ** |
1878 | - ** 5. In the case of duplicate command line arguments, the last one |
1879 | - ** specified wins. |
1880 | - ** |
1881 | - ** 6. In the case of names in the configuration file duplicating |
1882 | - ** names from the command line, the values from the command line |
1883 | - ** dominate. If there were multiple values for a given name |
1884 | - ** specified in the file, only the first one (the one returned by |
1885 | - ** the "[]" operator or get<>() method) is overridden. |
1886 | - **/ |
1887 | - unsigned int read(int argc, char* argv[], |
1888 | - const std::string & _filename); |
1889 | - /// clears the name/value list. |
1890 | - void clear(); |
1891 | - /// returns an iterator to the first item in the list. |
1892 | - iterator begin(); |
1893 | - /// returns an iterator one past the end of the list. |
1894 | - iterator end(); |
1895 | - /// True if there are no values, false otherwise. |
1896 | - bool empty(); |
1897 | - /// Returns the number of values stored. |
1898 | - unsigned int size(); |
1899 | - /** Returns the string value matching the supplied name. |
1900 | - ** |
1901 | - ** NOTE: the use of get<T>(key) or get<T>(key,default) is preferred. |
1902 | - ** This method is public to allow for specialized handling in the |
1903 | - ** rare cases where it may be required. |
1904 | - ** |
1905 | - ** If there are no matching names, "" is returned. Be aware that |
1906 | - ** "" is a valid value, so you can not use this to verify that |
1907 | - ** a given name was defined. Use exists() for that. |
1908 | - **/ |
1909 | - std::string operator [] (const std::string & key); |
1910 | - /** Returns all values associated with the supplied name. |
1911 | - ** |
1912 | - ** NOTE: the use of getall<T>(key) is preferred. This method is |
1913 | - ** public to allow specialized handling in rare case where it |
1914 | - ** may be required. |
1915 | - ** |
1916 | - ** If there are no values defined the strlist will be empty. |
1917 | - **/ |
1918 | - strlist all(const std::string & key); |
1919 | - /// True if the name exists, false otherwise. |
1920 | - bool exists(const std::string & key); |
1921 | - /** Use this to get all matching values. |
1922 | - ** |
1923 | - ** Usage: |
1924 | - ** |
1925 | - ** vector<type> mylist = conf_reader_object.getall<type>(key); |
1926 | - ** |
1927 | - ** type can be any standard type (string, int, double, etc.) or any |
1928 | - ** type for which the ">>" stream operator is defined. All values |
1929 | - ** with matching names that can map to the requested type will be |
1930 | - ** returned. Any that do not map will not be returned. |
1931 | - **/ |
1932 | - template < class T > |
1933 | - typename std::vector<T> getall(const std::string & key); |
1934 | - /** Use this to get the matching value. |
1935 | - ** |
1936 | - ** Useage: |
1937 | - ** |
1938 | - ** type myvar = get<type>(key); |
1939 | - ** |
1940 | - ** type can be any standard type (string, int, double, etc.) or any |
1941 | - ** type for which the ">>" stream operator is defined. The return |
1942 | - ** value is initialized to all zeros if no matching name is found or |
1943 | - ** if the first value with that name does not map to the requested |
1944 | - ** type. For the numeric types that results in zero being returned, |
1945 | - ** but be aware that more complex object may be in non-sensible |
1946 | - ** states if they were not found or could not map. Use exists() to |
1947 | - ** verify the existance of a given name if needed. |
1948 | - **/ |
1949 | - template < class T > |
1950 | - T get(const std::string & key); |
1951 | - /** Returns the value for the requested key, or the supplied default. |
1952 | - ** |
1953 | - ** Works exactly like get<>() with the exception that if the key |
1954 | - ** is not found in the list, the user supplied default value is |
1955 | - ** returned instead of 0 or an empty string. If the value exists but |
1956 | - ** can not map to the requested type, 0 or an empty string is |
1957 | - ** returned for the standard types. |
1958 | - **/ |
1959 | - template <class T> |
1960 | - T get(const std::string & key, const T & def); |
1961 | +private: |
1962 | + typedef std::multimap<std::string,std::string> value_list_type; |
1963 | + value_list_type values; |
1964 | +public: |
1965 | + /// conf_reader iterator, points to a conf_reader::pair |
1966 | + typedef value_list_type::iterator iterator; |
1967 | + /// conf_reader::pair is a std::pair<string,string> |
1968 | + typedef std::pair<std::string,std::string> pair; |
1969 | + /** No argument constructor; actually calls read() without a filename. |
1970 | + **/ |
1971 | + conf_reader(); |
1972 | + /** NOP virtual destructor to allow safe inheritance. |
1973 | + **/ |
1974 | + virtual ~conf_reader(); |
1975 | + /** Reads and parses the command line and the provided file. |
1976 | + ** |
1977 | + ** Returns the number of values stored. argc and argv are, of |
1978 | + ** course the same names you used as arguments to main(). Therefore |
1979 | + ** you can easily read all command line and configuration file |
1980 | + ** values like this: |
1981 | + ** |
1982 | + ** int main(int argc, char* argv[]) |
1983 | + ** |
1984 | + ** { |
1985 | + ** |
1986 | + ** conf_reader config; |
1987 | + ** |
1988 | + ** config.read(argc,argv,"my_conf_file"); |
1989 | + ** |
1990 | + ** ... |
1991 | + ** |
1992 | + ** } |
1993 | + ** |
1994 | + ** See read(filename,_clear) for a discription of how configuration |
1995 | + ** files are structured and parsed. This method unconditionally |
1996 | + ** clears the existing value list before starting. For command line |
1997 | + ** arguments the following rules are true. |
1998 | + ** |
1999 | + ** 1. The executable name (argv[0]) is stored as a value with the |
2000 | + ** name "__exec_name". |
2001 | + ** |
2002 | + ** 2. Command line arguments of the form "name=value" are parsed |
2003 | + ** stored as named values. |
2004 | + ** |
2005 | + ** 3. All other command line arguments are stored as names with |
2006 | + ** value = "". |
2007 | + ** |
2008 | + ** 4. A command line argument of form "configfile=filename" will |
2009 | + ** override the filename supplied as an argument to this method. |
2010 | + ** |
2011 | + ** 5. In the case of duplicate command line arguments, the last one |
2012 | + ** specified wins. |
2013 | + ** |
2014 | + ** 6. In the case of names in the configuration file duplicating |
2015 | + ** names from the command line, the values from the command line |
2016 | + ** dominate. If there were multiple values for a given name |
2017 | + ** specified in the file, only the first one (the one returned by |
2018 | + ** the "[]" operator or get<>() method) is overridden. |
2019 | + **/ |
2020 | + unsigned int read(int argc, char* argv[], |
2021 | + const std::string & _filename); |
2022 | + /// clears the name/value list. |
2023 | + void clear(); |
2024 | + /// returns an iterator to the first item in the list. |
2025 | + iterator begin(); |
2026 | + /// returns an iterator one past the end of the list. |
2027 | + iterator end(); |
2028 | + /// True if there are no values, false otherwise. |
2029 | + bool empty(); |
2030 | + /// Returns the number of values stored. |
2031 | + unsigned int size(); |
2032 | + /** Returns the string value matching the supplied name. |
2033 | + ** |
2034 | + ** NOTE: the use of get<T>(key) or get<T>(key,default) is preferred. |
2035 | + ** This method is public to allow for specialized handling in the |
2036 | + ** rare cases where it may be required. |
2037 | + ** |
2038 | + ** If there are no matching names, "" is returned. Be aware that |
2039 | + ** "" is a valid value, so you can not use this to verify that |
2040 | + ** a given name was defined. Use exists() for that. |
2041 | + **/ |
2042 | + std::string operator [] (const std::string & key); |
2043 | + /** Returns all values associated with the supplied name. |
2044 | + ** |
2045 | + ** NOTE: the use of getall<T>(key) is preferred. This method is |
2046 | + ** public to allow specialized handling in rare case where it |
2047 | + ** may be required. |
2048 | + ** |
2049 | + ** If there are no values defined the strlist will be empty. |
2050 | + **/ |
2051 | + strlist all(const std::string & key); |
2052 | + /// True if the name exists, false otherwise. |
2053 | + bool exists(const std::string & key); |
2054 | + /** Use this to get all matching values. |
2055 | + ** |
2056 | + ** Usage: |
2057 | + ** |
2058 | + ** vector<type> mylist = conf_reader_object.getall<type>(key); |
2059 | + ** |
2060 | + ** type can be any standard type (string, int, double, etc.) or any |
2061 | + ** type for which the ">>" stream operator is defined. All values |
2062 | + ** with matching names that can map to the requested type will be |
2063 | + ** returned. Any that do not map will not be returned. |
2064 | + **/ |
2065 | + template < class T > |
2066 | + typename std::vector<T> getall(const std::string & key); |
2067 | + /** Use this to get the matching value. |
2068 | + ** |
2069 | + ** Useage: |
2070 | + ** |
2071 | + ** type myvar = get<type>(key); |
2072 | + ** |
2073 | + ** type can be any standard type (string, int, double, etc.) or any |
2074 | + ** type for which the ">>" stream operator is defined. The return |
2075 | + ** value is initialized to all zeros if no matching name is found or |
2076 | + ** if the first value with that name does not map to the requested |
2077 | + ** type. For the numeric types that results in zero being returned, |
2078 | + ** but be aware that more complex object may be in non-sensible |
2079 | + ** states if they were not found or could not map. Use exists() to |
2080 | + ** verify the existance of a given name if needed. |
2081 | + **/ |
2082 | + template < class T > |
2083 | + T get(const std::string & key); |
2084 | + /** Returns the value for the requested key, or the supplied default. |
2085 | + ** |
2086 | + ** Works exactly like get<>() with the exception that if the key |
2087 | + ** is not found in the list, the user supplied default value is |
2088 | + ** returned instead of 0 or an empty string. If the value exists but |
2089 | + ** can not map to the requested type, 0 or an empty string is |
2090 | + ** returned for the standard types. |
2091 | + **/ |
2092 | + template <class T> |
2093 | + T get(const std::string & key, const T & def); |
2094 | +private: |
2095 | + std::string filename; |
2096 | +protected: |
2097 | + /** Reads and parses a configuration file. |
2098 | + ** |
2099 | + ** Returns the number of values stored. |
2100 | + ** |
2101 | + ** The optional parameter _clear when true clears the currently |
2102 | + ** stored list of values. if false the new values read will be added |
2103 | + ** to the existing list. |
2104 | + ** |
2105 | + ** If the file named can not be processed completely, a warning |
2106 | + ** message is published to cerr. |
2107 | + ** |
2108 | + ** Configuration files are defined as follows. |
2109 | + ** |
2110 | + ** 1. Files are read line by line. No value can cross a newline |
2111 | + ** (and at least in this version) or include one. The good |
2112 | + ** news is that you are allowed up to 16k for each line. |
2113 | + ** |
2114 | + ** 2. values are specifed in name/value pairs, one per line, with |
2115 | + ** the name first, followed by whitespace, followed by the |
2116 | + ** value. Values may include whitespace. All leading and trailing |
2117 | + ** whitespace is removed from both the name and the value. |
2118 | + ** |
2119 | + ** 3. Comments start with a \# symbol; all text following a \# is |
2120 | + ** ignored. If you need to use \# in a name or value, escape |
2121 | + ** it with a backslash instead. |
2122 | + ** |
2123 | + ** 4. Duplicate names are allowed. |
2124 | + ** |
2125 | + ** 5. Names without values will be stored with "" as the value. |
2126 | + ** |
2127 | + ** 6. A configuration file may include another configuration file |
2128 | + ** automatically by the use of the "*INCLUDE" reserved name. |
2129 | + ** When this name is found, it's value is used as the name of |
2130 | + ** the new file to be read. |
2131 | + **/ |
2132 | + unsigned int read(const std::string & _filename = "", bool _clear=true); |
2133 | }; |
2134 | |
2135 | typedef singleton<conf_reader> global_conf_reader; |
2136 | |
2137 | template < class T > |
2138 | - typename std::vector<T> conf_reader::getall(const std::string & key) |
2139 | -{ |
2140 | - strlist tvals = all(key); |
2141 | - std::vector<T> returnme; |
2142 | - if (typeid(T) == typeid(std::string)) |
2143 | - { |
2144 | - // T is a std::string.. we can do this quickly. |
2145 | - strlist * wl = (strlist *) &returnme; |
2146 | - *wl = tvals; |
2147 | - } |
2148 | - else |
2149 | - { |
2150 | - // T is non-string.. will require more playing around. |
2151 | - unsigned int limit = tvals.size(); |
2152 | - for (unsigned int i = 0; i < limit; i++) |
2153 | - { |
2154 | - try |
2155 | - { |
2156 | - returnme.push_back(boost::lexical_cast<T>(tvals[i])); |
2157 | - } |
2158 | - catch (...) {}; |
2159 | - }; |
2160 | - }; |
2161 | - return returnme; |
2162 | -}; |
2163 | - |
2164 | -template < class T > |
2165 | - T conf_reader::get(const std::string & key) |
2166 | -{ |
2167 | - conf_reader & me = *this; |
2168 | - std::string tval = me[key]; |
2169 | - T returnme; |
2170 | - // initialize the return value to nulls |
2171 | - // Needed for the numeric types, but bad for strings. |
2172 | - if (typeid(T) != typeid(std::string)) |
2173 | - { |
2174 | - // null out the working area (death for strings!) |
2175 | - memset(&returnme,0,sizeof(T)); |
2176 | - }; |
2177 | - // This does appear to work for all the standard types. |
2178 | - if (tval != "") |
2179 | - { |
2180 | - try |
2181 | - { |
2182 | - returnme = boost::lexical_cast<T>(tval); |
2183 | - } |
2184 | - catch (...) {}; |
2185 | - }; |
2186 | - return returnme; |
2187 | -}; |
2188 | - |
2189 | -template < class T > |
2190 | - T conf_reader::get(const std::string & key, const T & def) |
2191 | -{ |
2192 | - if (exists(key)) { return get<T>(key); } |
2193 | - else { return def; }; |
2194 | + typename std::vector<T> conf_reader::getall(const std::string & key) |
2195 | +{ |
2196 | + strlist tvals = all(key); |
2197 | + std::vector<T> returnme; |
2198 | + if (typeid(T) == typeid(std::string)) |
2199 | + { |
2200 | + // T is a std::string.. we can do this quickly. |
2201 | + strlist * wl = (strlist *) &returnme; |
2202 | + *wl = tvals; |
2203 | + } |
2204 | + else |
2205 | + { |
2206 | + // T is non-string.. will require more playing around. |
2207 | + unsigned int limit = tvals.size(); |
2208 | + for (unsigned int i = 0; i < limit; i++) |
2209 | + { |
2210 | + try |
2211 | + { |
2212 | + returnme.push_back(boost::lexical_cast<T>(tvals[i])); |
2213 | + } |
2214 | + catch (...) {}; |
2215 | + }; |
2216 | + }; |
2217 | + return returnme; |
2218 | +}; |
2219 | + |
2220 | +template < class T > |
2221 | + T conf_reader::get(const std::string & key) |
2222 | +{ |
2223 | + conf_reader & me = *this; |
2224 | + std::string tval = me[key]; |
2225 | + T returnme; |
2226 | + // initialize the return value to nulls |
2227 | + // Needed for the numeric types, but bad for strings. |
2228 | + if (typeid(T) != typeid(std::string)) |
2229 | + { |
2230 | + // null out the working area (death for strings!) |
2231 | + memset(&returnme,0,sizeof(T)); |
2232 | + }; |
2233 | + // This does appear to work for all the standard types. |
2234 | + if (tval != "") |
2235 | + { |
2236 | + try |
2237 | + { |
2238 | + returnme = boost::lexical_cast<T>(tval); |
2239 | + } |
2240 | + catch (...) {}; |
2241 | + }; |
2242 | + return returnme; |
2243 | +}; |
2244 | + |
2245 | +template < class T > |
2246 | + T conf_reader::get(const std::string & key, const T & def) |
2247 | +{ |
2248 | + if (exists(key)) { return get<T>(key); } |
2249 | + else { return def; }; |
2250 | }; |
2251 | |
2252 | }; // namespace nrtb |
2253 | |
2254 | -#endif // ricklib_confreader_h |
2255 | +#endif // nrtb_confreader_h |
2256 | |
2257 | |
2258 | === modified file 'cpp/common/confreader/conftest.cpp' |
2259 | --- obsolete/Cpp/common/confreader/conftest.cpp 2011-08-13 15:06:08 +0000 |
2260 | +++ cpp/common/confreader/conftest.cpp 2013-08-09 21:47:12 +0000 |
2261 | @@ -19,54 +19,56 @@ |
2262 | /* confreader test program */ |
2263 | |
2264 | #include "confreader.h" |
2265 | -#include <log_setup.h> |
2266 | #include <iostream> |
2267 | -#include "Poco/Logger.h" |
2268 | -#include "Poco/SimpleFileChannel.h" |
2269 | -//#include "Poco/AutoPtr.h" |
2270 | |
2271 | using namespace nrtb; |
2272 | using namespace std; |
2273 | |
2274 | +log_queue lq; |
2275 | +log_file_writer writer(lq, "conf_test.log"); |
2276 | + |
2277 | int main(int argc, char* argv[]) |
2278 | { |
2279 | bool set_if_failed = false; |
2280 | - setup_global_logging("conf_test.log"); |
2281 | - Poco::Logger & log = Poco::Logger::get("conftest"); |
2282 | - log.information("=-=-=-=-=-= conftest Init =-=-=-=-=-=-="); |
2283 | - global_conf_reader & config = global_conf_reader::get_instance(); |
2284 | + log_recorder log("config_test",lq); |
2285 | + log.info("=-=-=-=-=-= conftest Init =-=-=-=-=-=-="); |
2286 | + conf_reader & config = global_conf_reader::get_reference(); |
2287 | + |
2288 | try |
2289 | { |
2290 | - log.information("Starting read"); |
2291 | - config.read(argc,argv,"test.config"); |
2292 | + log.info("Starting read"); |
2293 | + config.read(argc,argv,"test.config"); |
2294 | } |
2295 | catch (...) |
2296 | { |
2297 | - set_if_failed = true; |
2298 | - cerr << "Failed reading the configuration." << endl; |
2299 | + set_if_failed = true; |
2300 | + cerr << "Failed reading the configuration." << endl; |
2301 | + log.severe("Failed reading the configuration."); |
2302 | }; |
2303 | if (config.size() != 12) |
2304 | { |
2305 | - set_if_failed = true; |
2306 | - cerr << "Did not find 12 parameters." << endl; |
2307 | + set_if_failed = true; |
2308 | + cerr << "Did not find 12 parameters." << endl; |
2309 | + log.severe("Did not find 12 parameters."); |
2310 | }; |
2311 | // iterator test |
2312 | try |
2313 | { |
2314 | - conf_reader::iterator c = config.begin(); |
2315 | - conf_reader::iterator e = config.end(); |
2316 | - while (c != e) |
2317 | - { |
2318 | - cout << "\t\"" << c->first << "\"=\"" << c->second |
2319 | - << "\"" << endl; |
2320 | - c++; |
2321 | - }; |
2322 | + conf_reader::iterator c = config.begin(); |
2323 | + conf_reader::iterator e = config.end(); |
2324 | + while (c != e) |
2325 | + { |
2326 | + cout << "\t\"" << c->first << "\"=\"" << c->second |
2327 | + << "\"" << endl; |
2328 | + c++; |
2329 | + }; |
2330 | } |
2331 | catch (...) |
2332 | { |
2333 | - set_if_failed = true; |
2334 | - cerr << "Iterator test failed." << endl; |
2335 | - }; |
2336 | + set_if_failed = true; |
2337 | + cerr << "Iterator test failed." << endl; |
2338 | + log.severe("Iterator test failed."); |
2339 | +}; |
2340 | // template test. |
2341 | int test = config.get<int>("test",-1); |
2342 | int test2 = config.get<int>("test2",-1); |
2343 | @@ -74,56 +76,60 @@ |
2344 | double test4 = config.get<double>("test",-1); |
2345 | double test5 = config.get<double>("test2",-1); |
2346 | cout << "(int) test = " << test |
2347 | - << "\n(int) test2 = " << test2 |
2348 | - << "\n(string) test3 = \"" << test3 << "\"" |
2349 | - << "\n(double) test = " << test4 |
2350 | - << "\n(double) test2 = " << test5 |
2351 | - << endl; |
2352 | + << "\n(int) test2 = " << test2 |
2353 | + << "\n(string) test3 = \"" << test3 << "\"" |
2354 | + << "\n(double) test = " << test4 |
2355 | + << "\n(double) test2 = " << test5 |
2356 | + << endl; |
2357 | if ( |
2358 | - (test != 1) or (test2 != 0) |
2359 | - or (test3 != "jack danials") |
2360 | - or (test4 != 1.0) or (test5 != 71.837486) |
2361 | + (test != 1) or (test2 != 0) |
2362 | + or (test3 != "jack danials") |
2363 | + or (test4 != 1.0) or (test5 != 71.837486) |
2364 | ) |
2365 | { |
2366 | - set_if_failed = true; |
2367 | - cerr << "** Template test failed." << endl; |
2368 | + set_if_failed = true; |
2369 | + cerr << "** Template test failed." << endl; |
2370 | + log.severe("** Template test failed."); |
2371 | }; |
2372 | // exists test. |
2373 | cout << "?var \"--doit\" exists? " |
2374 | - << (config.exists("--doit") ? "Yes" : "No") |
2375 | - << endl; |
2376 | + << (config.exists("--doit") ? "Yes" : "No") |
2377 | + << endl; |
2378 | if (!config.exists("--doit")) |
2379 | { |
2380 | - set_if_failed = true; |
2381 | - cerr << "exists() test failed." << endl; |
2382 | + set_if_failed = true; |
2383 | + cerr << "exists() test failed." << endl; |
2384 | + log.severe("exists() test failed."); |
2385 | }; |
2386 | vector<int> intlist = config.getall<int>("test"); |
2387 | cout << "valid int \"test\" values:" << endl; |
2388 | for (unsigned int i=0; i < intlist.size(); i++) |
2389 | { |
2390 | - cout << "\t" << i << ": " << intlist[i] << endl; |
2391 | + cout << "\t" << i << ": " << intlist[i] << endl; |
2392 | }; |
2393 | if (intlist.size() != 2) |
2394 | { |
2395 | - set_if_failed = true; |
2396 | - cerr << "getall<int>() did not find 2 parameters." << endl; |
2397 | + set_if_failed = true; |
2398 | + cerr << "getall<int>() did not find 2 parameters." << endl; |
2399 | + log.severe("getall<int>() did not find 2 parameters."); |
2400 | }; |
2401 | strlist strings = config.getall<string>("test"); |
2402 | cout << "valid string \"test\" values:" << endl; |
2403 | for (unsigned int i=0; i < strings.size(); i++) |
2404 | { |
2405 | - cout << "\t" << i << ": " << strings[i] << endl; |
2406 | + cout << "\t" << i << ": " << strings[i] << endl; |
2407 | }; |
2408 | if (strings.size() != 3) |
2409 | { |
2410 | - set_if_failed = true; |
2411 | - cerr << "getall<string>() did not find 3 parameters." << endl; |
2412 | + set_if_failed = true; |
2413 | + cerr << "getall<string>() did not find 3 parameters." << endl; |
2414 | + log.severe("getall<string>() did not find 3 parameters."); |
2415 | }; |
2416 | if (set_if_failed) |
2417 | { |
2418 | - cerr << "** ntrb::conf_reader UNIT TEST FAILED. **" << endl; |
2419 | - log.fatal("UNIT TEST FAILED"); |
2420 | + cerr << "** ntrb::conf_reader UNIT TEST FAILED. **" << endl; |
2421 | + log.critical("UNIT TEST FAILED"); |
2422 | }; |
2423 | - log.information("Run Complete"); |
2424 | + log.info("Run Complete"); |
2425 | return set_if_failed; |
2426 | }; |
2427 | |
2428 | === modified file 'cpp/common/linear_queue/Makefile' |
2429 | --- obsolete/Cpp/common/linear_queue/Makefile 2012-04-06 17:18:50 +0000 |
2430 | +++ cpp/common/linear_queue/Makefile 2013-08-09 21:47:12 +0000 |
2431 | @@ -16,6 +16,8 @@ |
2432 | # |
2433 | #*********************************************** |
2434 | |
2435 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
2436 | + |
2437 | lib: linear_queue_test |
2438 | @./linear_queue_test |
2439 | @cp -v linear_queue.h ../include |
2440 | @@ -23,8 +25,8 @@ |
2441 | |
2442 | linear_queue_test: linear_queue.h linear_queue_test.cpp |
2443 | @rm -f linear_queue_test |
2444 | - g++ -c linear_queue_test.cpp -I../include -std=gnu++0x |
2445 | - g++ -o linear_queue_test linear_queue_test.o ../obj/common.o ../obj/base_thread.o -lpthread -std=gnu++0x |
2446 | + g++ -c linear_queue_test.cpp -I../include ${switches} |
2447 | + g++ -o linear_queue_test linear_queue_test.o -lpthread ${switches} |
2448 | |
2449 | clean: |
2450 | @rm -rvf *.o linear_queue_test ../include/linear_queue.h *.log ../obj/linear_queue.o |
2451 | |
2452 | === modified file 'cpp/common/linear_queue/linear_queue.h' |
2453 | --- obsolete/Cpp/common/linear_queue/linear_queue.h 2011-10-07 00:01:15 +0000 |
2454 | +++ cpp/common/linear_queue/linear_queue.h 2013-08-09 21:47:12 +0000 |
2455 | @@ -19,9 +19,11 @@ |
2456 | #ifndef nrtb_linear_queue_h |
2457 | #define nrtb_linear_queue_h |
2458 | |
2459 | -#include <iostream> |
2460 | -#include <base_thread.h> |
2461 | -#include <list> |
2462 | +#include <atomic> |
2463 | +#include <mutex> |
2464 | +#include <condition_variable> |
2465 | +#include <queue> |
2466 | +#include <abs_queue.h> |
2467 | |
2468 | namespace nrtb |
2469 | { |
2470 | @@ -45,120 +47,7 @@ |
2471 | * passing data to another set of threads. |
2472 | ********************************************************/ |
2473 | template <class T> |
2474 | -class linear_queue |
2475 | -{ |
2476 | -public: |
2477 | - class queue_not_ready: public base_exception {}; |
2478 | - |
2479 | - /********************************************* |
2480 | - * creates the queue with the specified |
2481 | - * number of elements. |
2482 | - *********************************************/ |
2483 | - linear_queue(); |
2484 | - |
2485 | - /********************************************* |
2486 | - * releases all items in the queue |
2487 | - *********************************************/ |
2488 | - virtual ~linear_queue(); |
2489 | - |
2490 | - /********************************************* |
2491 | - * Puts an item in the queue. |
2492 | - *********************************************/ |
2493 | - void push(T item); |
2494 | - |
2495 | - /********************************************* |
2496 | - * Pops the next item off the queue, blocking |
2497 | - * if needed until an item becomes available. |
2498 | - *********************************************/ |
2499 | - T pop(); |
2500 | - |
2501 | - /********************************************* |
2502 | - * puts the queue in shutdown mode. |
2503 | - *********************************************/ |
2504 | - void shutdown(); |
2505 | - |
2506 | - // returns the number of items in the queue |
2507 | - int size(); |
2508 | - // clears the buffer, data will be discarded. |
2509 | - void clear(); |
2510 | - |
2511 | -protected: |
2512 | - |
2513 | - std::list<T> buffer; |
2514 | - cond_variable buffer_lock; |
2515 | - bool ready; |
2516 | -}; |
2517 | - |
2518 | -template <class T> |
2519 | -linear_queue<T>::linear_queue() |
2520 | -{ |
2521 | - ready = true; |
2522 | -}; |
2523 | - |
2524 | -template <class T> |
2525 | -linear_queue<T>::~linear_queue() |
2526 | -{ |
2527 | -}; |
2528 | - |
2529 | -template <class T> |
2530 | -void linear_queue<T>::push(T item) |
2531 | -{ |
2532 | - if (ready) |
2533 | - { |
2534 | - scope_lock lock(buffer_lock); |
2535 | - buffer.push_back(item); |
2536 | - buffer_lock.signal(); |
2537 | - } |
2538 | - else |
2539 | - { |
2540 | - queue_not_ready e; |
2541 | - throw e; |
2542 | - } |
2543 | -}; |
2544 | - |
2545 | -template <class T> |
2546 | -T linear_queue<T>::pop() |
2547 | -{ |
2548 | - scope_lock lock(buffer_lock); |
2549 | - while (buffer.empty() && ready) |
2550 | - buffer_lock.wait(); |
2551 | - if (!ready) |
2552 | - { |
2553 | - queue_not_ready e; |
2554 | - throw e; |
2555 | - }; |
2556 | - T returnme = buffer.front(); |
2557 | - buffer.pop_front(); |
2558 | - return returnme; |
2559 | -}; |
2560 | - |
2561 | -template <class T> |
2562 | -void linear_queue<T>::shutdown() |
2563 | -{ |
2564 | - try |
2565 | - { |
2566 | - scope_lock lock(buffer_lock); |
2567 | - ready = false; |
2568 | - buffer_lock.broadcast_signal(); |
2569 | - buffer.clear(); |
2570 | - } |
2571 | - catch (...) {} |
2572 | -} |
2573 | - |
2574 | - |
2575 | -template <class T> |
2576 | -int linear_queue<T>::size() |
2577 | -{ |
2578 | - scope_lock lock(buffer_lock); |
2579 | - return buffer.size(); |
2580 | -}; |
2581 | - |
2582 | -template <class T> |
2583 | -void linear_queue<T>::clear() |
2584 | -{ |
2585 | - scope_lock lock(buffer_lock); |
2586 | - buffer.clear(); |
2587 | -}; |
2588 | +class linear_queue : public abs_queue<T,std::queue<T>> {}; |
2589 | |
2590 | } // namespace nrtb |
2591 | |
2592 | |
2593 | === modified file 'cpp/common/linear_queue/linear_queue_test.cpp' |
2594 | --- obsolete/Cpp/common/linear_queue/linear_queue_test.cpp 2011-10-07 00:01:15 +0000 |
2595 | +++ cpp/common/linear_queue/linear_queue_test.cpp 2013-08-09 21:47:12 +0000 |
2596 | @@ -15,81 +15,45 @@ |
2597 | along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
2598 | |
2599 | **********************************************/ |
2600 | - |
2601 | + |
2602 | +#include <unistd.h> // included for usleep() |
2603 | #include <string> |
2604 | #include <iostream> |
2605 | #include "linear_queue.h" |
2606 | -#include <boost/shared_ptr.hpp> |
2607 | +#include <memory> |
2608 | +#include <atomic> |
2609 | +#include <future> |
2610 | |
2611 | using namespace nrtb; |
2612 | using namespace std; |
2613 | |
2614 | typedef linear_queue<int> test_queue; |
2615 | -typedef boost::shared_ptr<test_queue> queue_p; |
2616 | +typedef shared_ptr<test_queue> queue_p; |
2617 | |
2618 | -class consumer_task: public thread |
2619 | +int consumer_task(string name, queue_p input) |
2620 | { |
2621 | -public: |
2622 | - |
2623 | - consumer_task(string n, queue_p buffer) |
2624 | - { |
2625 | - name = n; |
2626 | - input = buffer; |
2627 | - count = 0; |
2628 | - }; |
2629 | - |
2630 | - ~consumer_task() |
2631 | - { |
2632 | - cout << ">> in " << name << "::~consumer_task()" << endl; |
2633 | - try |
2634 | - { |
2635 | - this->thread::~thread(); |
2636 | - input.reset(); |
2637 | - } |
2638 | - catch (...) {}; |
2639 | - cout << "<< leaving " << name << "::~consumer_task()" << endl; |
2640 | - }; |
2641 | - |
2642 | - int get_count() { return count; }; |
2643 | - |
2644 | - void run() |
2645 | - { |
2646 | - try |
2647 | - { |
2648 | - while (true) |
2649 | - { |
2650 | - int num = input->pop(); |
2651 | - { |
2652 | - static mutex console; |
2653 | - scope_lock lock(console); |
2654 | - cout << name << " picked up " << num |
2655 | - << endl; |
2656 | - }; |
2657 | - count++; |
2658 | - lastnum = num; |
2659 | - yield(); |
2660 | - } |
2661 | - } |
2662 | - catch (...) {}; |
2663 | - }; |
2664 | - |
2665 | -protected: |
2666 | - // link to the feed queue |
2667 | - queue_p input; |
2668 | - // a name to report |
2669 | - string name; |
2670 | - // number of items processed |
2671 | - int count; |
2672 | - // last number caught |
2673 | - int lastnum; |
2674 | + bool ready {true}; |
2675 | + int count {0}; |
2676 | + try |
2677 | + { |
2678 | + while (ready) |
2679 | + { |
2680 | + int num = input->pop(); |
2681 | + count++; |
2682 | + usleep(1); |
2683 | + } |
2684 | + } |
2685 | + catch (...) |
2686 | + { |
2687 | + // exit if we get any exception. |
2688 | + ready = false; |
2689 | + }; |
2690 | + return count; |
2691 | }; |
2692 | |
2693 | -typedef boost::shared_ptr<consumer_task> task_p; |
2694 | - |
2695 | - |
2696 | int main() |
2697 | { |
2698 | - int er_count = 0; |
2699 | + cout << "***** linear_queue unit test ******" << endl; |
2700 | /************************************************ |
2701 | * Load queue and then cook it down... |
2702 | ***********************************************/ |
2703 | @@ -97,14 +61,15 @@ |
2704 | queue_p q1(new test_queue()); |
2705 | for (int i=0; i<100; i++) |
2706 | { |
2707 | - q1->push(i); |
2708 | + q1->push(i); |
2709 | }; |
2710 | - // the queue should be loaded with 50-99 |
2711 | + // the queue should be loaded with 0-99 |
2712 | // attach a thread and process it. |
2713 | - task_p p1(new consumer_task("task 1",q1)); |
2714 | - p1->start(); |
2715 | + auto t1 = async(launch::async,consumer_task,"task 1",q1); |
2716 | while (q1->size()) usleep(100); |
2717 | - cout << "cp 1 " << p1->get_count() << endl; |
2718 | + cout << "cp 1 " |
2719 | + << q1->in_count << ":" |
2720 | + << q1->out_count << endl; |
2721 | /************************************************ |
2722 | * now that the preload is exhasted, shove items |
2723 | * in one at a time to make sure each is picked |
2724 | @@ -112,40 +77,42 @@ |
2725 | ***********************************************/ |
2726 | for (int i=200; i<225; i++) |
2727 | { |
2728 | - q1->push(i); |
2729 | - usleep(100); |
2730 | + q1->push(i); |
2731 | + usleep(100); |
2732 | }; |
2733 | - cout << "cp 2 " << p1->get_count() << endl; |
2734 | + cout << "cp 2 " |
2735 | + << q1->in_count << ":" |
2736 | + << q1->out_count << endl; |
2737 | /************************************************ |
2738 | * Last check; attach a second thread to the queue |
2739 | * and make sure both are servicing it. |
2740 | ***********************************************/ |
2741 | - task_p p2(new consumer_task("task 2",q1)); |
2742 | - p2->start(); |
2743 | + auto t2 = async(launch::async,consumer_task,"task 2",q1); |
2744 | for (int i=300; i<325; i++) |
2745 | { |
2746 | - q1->push(i); |
2747 | + q1->push(i); |
2748 | }; |
2749 | while (q1->size()) usleep(100); |
2750 | // shut it all down |
2751 | q1->shutdown(); |
2752 | - p1->join(); |
2753 | - p2->join(); |
2754 | // important numbers |
2755 | - int tot_items = p1->get_count() + p2->get_count(); |
2756 | - int p1_items = p1->get_count() - 125; |
2757 | - int p2_items = p2->get_count(); |
2758 | - // release she threads and queues. |
2759 | - p1.reset(); |
2760 | - p2.reset(); |
2761 | + int t1_count = t1.get(); |
2762 | + int t2_count = t2.get(); |
2763 | + int q1_in = q1->in_count; |
2764 | + int q1_out = q1->out_count; |
2765 | + // release the queues. |
2766 | q1.reset(); |
2767 | // do some reporting. |
2768 | cout << "cp 3 " |
2769 | - << tot_items |
2770 | - << " [125 + (" << p1_items |
2771 | - << " + " << p2_items |
2772 | - << ")]" << endl; |
2773 | - bool passed = (tot_items == 150); |
2774 | + << q1_in << ":" << q1_out |
2775 | + << " t1=" << t1_count |
2776 | + << " t2=" << t2_count |
2777 | + << endl; |
2778 | + bool passed = (q1_in == q1_out) |
2779 | + and (q1_out == (t1_count + t2_count)); |
2780 | + cout << "***** linear_queue TEST " |
2781 | + << (passed ? "PASSED" : "FAILED") |
2782 | + << " ******" << endl; |
2783 | // inverted logic needed because 0 is good for |
2784 | // return codes. |
2785 | return !passed; |
2786 | |
2787 | === modified file 'cpp/common/logger/Makefile' |
2788 | --- obsolete/Cpp/common/logger/Makefile 2012-04-06 17:42:05 +0000 |
2789 | +++ cpp/common/logger/Makefile 2013-08-09 21:47:12 +0000 |
2790 | @@ -1,5 +1,5 @@ |
2791 | #*********************************************** |
2792 | -#This file is part of the NRTB project (https://launchpad.net/nrtb). |
2793 | +# This file is part of the NRTB project (https://launchpad.net/nrtb). |
2794 | # |
2795 | # NRTB is free software: you can redistribute it and/or modify |
2796 | # it under the terms of the GNU General Public License as published by |
2797 | @@ -16,27 +16,25 @@ |
2798 | # |
2799 | #*********************************************** |
2800 | |
2801 | -lib: log_test |
2802 | - @echo "Testing..." |
2803 | - @rm -f test_output.log |
2804 | - @./log_test |
2805 | - @grep "Program run complete." test_output.log |
2806 | - @cp -fv log_setup.h ../include |
2807 | - @cp -fv log_setup.o ../obj |
2808 | - |
2809 | - |
2810 | -log_setup.o: log_setup.h log_setup.cpp Makefile |
2811 | - @rm -f log_setup.o |
2812 | - g++ -c log_setup.cpp -I ../include -std=gnu++0x |
2813 | - |
2814 | -log_test: log_setup.o log_test.cpp Makefile |
2815 | - @rm -vf log_test |
2816 | - g++ -c log_test.cpp -I../include -std=gnu++0x |
2817 | - g++ -o log_test log_setup.o log_test.o -lPocoFoundation -std=gnu++0x |
2818 | -# g++ -g common_test.cpp -idirafter . -o common_test |
2819 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
2820 | + |
2821 | +lib: logger_test |
2822 | + @./logger_test |
2823 | + @cp -v logger.h ../include/ |
2824 | + @cp -v logger.o ../obj/ |
2825 | + @echo build complete |
2826 | + |
2827 | +logger_test: logger.o logger_test.cpp |
2828 | + @rm -f logger_test |
2829 | + g++ -c -O3 logger_test.cpp -I ../include ${switches} |
2830 | + g++ -o logger_test logger_test.o logger.o -lpthread ${switches} |
2831 | + |
2832 | + |
2833 | +logger.o: logger.cpp logger.h Makefile |
2834 | + @rm -f logger.o |
2835 | + g++ -c -O3 logger.cpp -I ../include ${switches} |
2836 | |
2837 | clean: |
2838 | - @rm -vf *.o log_test ../include/log_setup.h ../obj/log_setup.o test_output.log |
2839 | - |
2840 | - |
2841 | + @rm -vf *.o ../include/logger.h logger_test |
2842 | + @echo all objects and executables have been erased. |
2843 | |
2844 | |
2845 | === added file 'cpp/common/logger/logger.cpp' |
2846 | --- cpp/common/logger/logger.cpp 1970-01-01 00:00:00 +0000 |
2847 | +++ cpp/common/logger/logger.cpp 2013-08-09 21:47:12 +0000 |
2848 | @@ -0,0 +1,141 @@ |
2849 | +/*********************************************** |
2850 | + This file is part of the NRTB project (https://*launchpad.net/nrtb). |
2851 | + |
2852 | + NRTB is free software: you can redistribute it and/or modify |
2853 | + it under the terms of the GNU General Public License as published by |
2854 | + the Free Software Foundation, either version 3 of the License, or |
2855 | + (at your option) any later version. |
2856 | + |
2857 | + NRTB is distributed in the hope that it will be useful, |
2858 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
2859 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2860 | + GNU General Public License for more details. |
2861 | + |
2862 | + You should have received a copy of the GNU General Public License |
2863 | + along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
2864 | + |
2865 | + **********************************************/ |
2866 | + |
2867 | +// see base_socket.h for documentation |
2868 | + |
2869 | +#include "logger.h" |
2870 | +#include <fstream> |
2871 | +#include <iomanip> |
2872 | +#include <sstream> |
2873 | +#include <ctime> |
2874 | +#include <unistd.h> |
2875 | + |
2876 | +namespace nrtb |
2877 | +{ |
2878 | + |
2879 | +std::string sev2text(log_sev s) |
2880 | +{ |
2881 | + std::string returnme; |
2882 | + switch (s) |
2883 | + { |
2884 | + case log_sev::critical : returnme = "CRITICAL"; break; |
2885 | + case log_sev::severe : returnme = "SEVERE"; break; |
2886 | + case log_sev::warning : returnme = "WARNING"; break; |
2887 | + case log_sev::info : returnme = "INFO"; break; |
2888 | + case log_sev::trace : returnme = "TRACE"; break; |
2889 | + default: returnme = "Undefined"; |
2890 | + }; |
2891 | + return returnme; |
2892 | +}; |
2893 | + |
2894 | +log_record::log_record(log_sev s, std::string c, std::string m) |
2895 | +{ |
2896 | + created = std::time(NULL); |
2897 | + severity = s; |
2898 | + component = c; |
2899 | + message = m; |
2900 | +}; |
2901 | + |
2902 | +void log_recorder::operator()(log_sev sev, std::string msg) |
2903 | +{ |
2904 | + log_record tr(sev, component, msg); |
2905 | + my_queue.push(tr); |
2906 | +}; |
2907 | + |
2908 | +void log_recorder::critical(std::string msg) |
2909 | +{ |
2910 | + (*this)(log_sev::critical,msg); |
2911 | +}; |
2912 | + |
2913 | +void log_recorder::severe(std::string msg) |
2914 | +{ |
2915 | + (*this)(log_sev::severe, msg); |
2916 | +}; |
2917 | + |
2918 | +void log_recorder::warning(std::string msg) |
2919 | +{ |
2920 | + (*this)(log_sev::warning, msg); |
2921 | +}; |
2922 | + |
2923 | +void log_recorder::info(std::string msg) |
2924 | +{ |
2925 | + (*this)(log_sev::info, msg); |
2926 | +}; |
2927 | + |
2928 | +void log_recorder::trace(std::string msg) |
2929 | +{ |
2930 | + (*this)(log_sev::trace, msg); |
2931 | +}; |
2932 | + |
2933 | +log_file_writer::log_file_writer(log_queue& queue, std::string filename) |
2934 | + : myqueue(queue) |
2935 | +{ |
2936 | + // start the writer |
2937 | + writer_process = |
2938 | + std::thread(log_file_writer::writer_thread, |
2939 | + std::ref(queue),filename); |
2940 | +}; |
2941 | + |
2942 | +void log_file_writer::close() |
2943 | +{ |
2944 | + // Hang around long enough to drain the queue. |
2945 | + while (myqueue.size()) |
2946 | + usleep(100); |
2947 | + // Shutdown the queue, terminate the worker thread. |
2948 | + myqueue.shutdown(); |
2949 | +}; |
2950 | + |
2951 | +log_file_writer::~log_file_writer() |
2952 | +{ |
2953 | + close(); |
2954 | + // Wait for the worker to close down. |
2955 | + if (writer_process.joinable()) |
2956 | + writer_process.join(); |
2957 | +}; |
2958 | + |
2959 | +void log_file_writer::writer_thread(log_queue& q, std::string fname) |
2960 | +{ |
2961 | + bool done {false}; |
2962 | + std::ofstream output; |
2963 | + output.open(fname); |
2964 | + while (!done) |
2965 | + { |
2966 | + try |
2967 | + { |
2968 | + log_record record = q.pop(); |
2969 | + std::tm tm = *std::localtime(&record.created); |
2970 | + std::stringstream s; |
2971 | + s << tm.tm_year + 1900 |
2972 | + << "-" << tm.tm_mon + 1 |
2973 | + << "-" << tm.tm_mday |
2974 | + << ":" << tm.tm_hour |
2975 | + << ":" << tm.tm_min |
2976 | + << ":" << tm.tm_sec |
2977 | + << "\t" << sev2text(record.severity) |
2978 | + << "\t" << record.component |
2979 | + << "\t" << record.message; |
2980 | + output << s.str() |
2981 | + << std::endl; |
2982 | + } |
2983 | + catch (...) { done = true; }; |
2984 | + }; |
2985 | + output.close(); |
2986 | +}; |
2987 | + |
2988 | +} // namqespace nrtb |
2989 | + |
2990 | |
2991 | === added file 'cpp/common/logger/logger.h' |
2992 | --- cpp/common/logger/logger.h 1970-01-01 00:00:00 +0000 |
2993 | +++ cpp/common/logger/logger.h 2013-08-09 21:47:12 +0000 |
2994 | @@ -0,0 +1,76 @@ |
2995 | +/*********************************************** |
2996 | + This file is part of the NRTB project (https://*launchpad.net/nrtb). |
2997 | + |
2998 | + NRTB is free software: you can redistribute it and/or modify |
2999 | + it under the terms of the GNU General Public License as published by |
3000 | + the Free Software Foundation, either version 3 of the License, or |
3001 | + (at your option) any later version. |
3002 | + |
3003 | + NRTB is distributed in the hope that it will be useful, |
3004 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
3005 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3006 | + GNU General Public License for more details. |
3007 | + |
3008 | + You should have received a copy of the GNU General Public License |
3009 | + along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
3010 | + |
3011 | + **********************************************/ |
3012 | + |
3013 | +#ifndef logger_header |
3014 | +#define logger_header |
3015 | + |
3016 | +#include <string> |
3017 | +#include <chrono> |
3018 | +#include <thread> |
3019 | +#include <ctime> |
3020 | +#include <linear_queue.h> |
3021 | + |
3022 | +namespace nrtb |
3023 | +{ |
3024 | + |
3025 | +enum class log_sev {critical,severe,warning,info,trace}; |
3026 | + |
3027 | +std::string sev2text(log_sev s); |
3028 | + |
3029 | +struct log_record |
3030 | +{ |
3031 | + log_record(log_sev s, std::string c, std::string m); |
3032 | + std::time_t created; |
3033 | + log_sev severity; |
3034 | + std::string component; |
3035 | + std::string message; |
3036 | +}; |
3037 | + |
3038 | +typedef linear_queue<log_record> log_queue; |
3039 | + |
3040 | +class log_recorder |
3041 | +{ |
3042 | +public: |
3043 | + log_recorder(std::string comp, log_queue & queue): |
3044 | + component(comp), my_queue(queue) {}; |
3045 | + void operator () (log_sev sev, std::string msg); |
3046 | + void critical(std::string msg); |
3047 | + void severe(std::string msg); |
3048 | + void warning(std::string msg); |
3049 | + void info(std::string msg); |
3050 | + void trace(std::string msg); |
3051 | +private: |
3052 | + log_queue & my_queue; |
3053 | + std::string component; |
3054 | +}; |
3055 | + |
3056 | +class log_file_writer |
3057 | +{ |
3058 | +public: |
3059 | + log_file_writer(log_queue & queue, std::string filename); |
3060 | + ~log_file_writer(); |
3061 | + void close(); |
3062 | +private: |
3063 | + log_queue & myqueue; |
3064 | + std::thread writer_process; |
3065 | + static void writer_thread(log_queue & q, std::string fname); |
3066 | +}; |
3067 | + |
3068 | +} // namepace nrtb |
3069 | + |
3070 | +#endif // logger_header |
3071 | |
3072 | === added file 'cpp/common/logger/logger_test.cpp' |
3073 | --- cpp/common/logger/logger_test.cpp 1970-01-01 00:00:00 +0000 |
3074 | +++ cpp/common/logger/logger_test.cpp 2013-08-09 21:47:12 +0000 |
3075 | @@ -0,0 +1,105 @@ |
3076 | +/*********************************************** |
3077 | + This file is part of the NRTB project (https://*launchpad.net/nrtb). |
3078 | + |
3079 | + NRTB is free software: you can redistribute it and/or modify |
3080 | + it under the terms of the GNU General Public License as published by |
3081 | + the Free Software Foundation, either version 3 of the License, or |
3082 | + (at your option) any later version. |
3083 | + |
3084 | + NRTB is distributed in the hope that it will be useful, |
3085 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
3086 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3087 | + GNU General Public License for more details. |
3088 | + |
3089 | + You should have received a copy of the GNU General Public License |
3090 | + along with NRTB. If not, see <http://www.gnu.org/licenses/>. |
3091 | + |
3092 | + **********************************************/ |
3093 | + |
3094 | +#include "logger.h" |
3095 | +#include <sstream> |
3096 | +#include <iostream> |
3097 | +#include <boost/concept_check.hpp> |
3098 | + |
3099 | +using namespace nrtb; |
3100 | +using namespace std; |
3101 | + |
3102 | +int ecount {0}; |
3103 | + |
3104 | +string stext_test(string a, log_sev b) |
3105 | +{ |
3106 | + stringstream s; |
3107 | + s << a << " " << (a == sev2text(b) ? "passed" : "failed"); |
3108 | + if (a != sev2text(b)) ecount++; |
3109 | + return s.str(); |
3110 | +}; |
3111 | + |
3112 | +int main() |
3113 | +{ |
3114 | + cout << "=========== logger unit test =============" |
3115 | + << endl; |
3116 | + |
3117 | + log_queue test_logger; |
3118 | + log_recorder log("Unit_Test",test_logger); |
3119 | + log_file_writer writer(test_logger,"test_log.log"); |
3120 | + |
3121 | + log.trace("Starting"); |
3122 | + for(auto i= 0; i<10; i++) |
3123 | + { |
3124 | + stringstream s; |
3125 | + s << "Log entry " << i; |
3126 | + log(log_sev::info,s.str()); |
3127 | + }; |
3128 | + |
3129 | + log.trace("sev2test() testing"); |
3130 | + log.info(stext_test("CRITICAL",log_sev::critical)); |
3131 | + log.info(stext_test("SEVERE",log_sev::severe)); |
3132 | + log.info(stext_test("WARNING",log_sev::warning)); |
3133 | + log.info(stext_test("INFO",log_sev::info)); |
3134 | + log.info(stext_test("TRACE",log_sev::trace)); |
3135 | + |
3136 | + log.trace("Shutting down"); |
3137 | + writer.close(); |
3138 | + |
3139 | + bool good = (test_logger.in_count == test_logger.out_count); |
3140 | + good = good and (ecount == 0); |
3141 | + |
3142 | + // test status billboard |
3143 | + cout << test_logger.in_count |
3144 | + << " : " << test_logger.out_count |
3145 | + << " : " << ecount |
3146 | + << endl; |
3147 | + if (!good) |
3148 | + cout << "Errors reported.. check log file." << endl; |
3149 | + cout << "=========== tcp_socket and server test complete =============" |
3150 | + << endl; |
3151 | + |
3152 | + return !good; // return code has reversed values. |
3153 | +}; |
3154 | + |
3155 | + |
3156 | + |
3157 | + |
3158 | + |
3159 | + |
3160 | + |
3161 | + |
3162 | + |
3163 | + |
3164 | + |
3165 | + |
3166 | + |
3167 | + |
3168 | + |
3169 | + |
3170 | + |
3171 | + |
3172 | + |
3173 | + |
3174 | + |
3175 | + |
3176 | + |
3177 | + |
3178 | + |
3179 | + |
3180 | + |
3181 | |
3182 | === modified file 'cpp/common/point/Makefile' |
3183 | --- obsolete/Cpp/common/point/Makefile 2012-04-06 17:42:40 +0000 |
3184 | +++ cpp/common/point/Makefile 2013-08-09 21:47:12 +0000 |
3185 | @@ -16,17 +16,16 @@ |
3186 | # |
3187 | #*********************************************** |
3188 | |
3189 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
3190 | + |
3191 | lib: common_test Makefile |
3192 | @echo "(2,3.5,7)" | ./common_test |
3193 | @cp -v triad.h ../include |
3194 | @echo nrtb::triad build complete |
3195 | |
3196 | -../include/common.h: |
3197 | - @cd ../common_rl; make lib |
3198 | - |
3199 | -common_test: common_test.cpp triad.h Makefile ../include/common.h |
3200 | +common_test: common_test.cpp triad.h Makefile |
3201 | @rm -vf common_test |
3202 | - g++ -O3 common_test.cpp -I ../include ../obj/common.o -o common_test -std=gnu++0x |
3203 | + g++ -O3 common_test.cpp -I ../include ../obj/common.o -o common_test ${switches} |
3204 | |
3205 | clean: |
3206 | @rm -vf *.o common_test ../include/triad.h |
3207 | |
3208 | === modified file 'cpp/common/point/common_test.cpp' |
3209 | --- obsolete/Cpp/common/point/common_test.cpp 2011-07-27 02:27:23 +0000 |
3210 | +++ cpp/common/point/common_test.cpp 2013-08-09 21:47:12 +0000 |
3211 | @@ -32,8 +32,8 @@ |
3212 | cout << "\t" << prompt << " = " << val << endl; |
3213 | if (val != right) |
3214 | { |
3215 | - ec++; |
3216 | - cerr << "\t\tTest Failed: Answer should be " << val << endl; |
3217 | + ec++; |
3218 | + cerr << "\t\tTest Failed: Answer should be " << val << endl; |
3219 | } |
3220 | return ec; |
3221 | }; |
3222 | @@ -43,75 +43,75 @@ |
3223 | cout << "\t" << prompt << " = " << val << endl; |
3224 | if (val != right) |
3225 | { |
3226 | - ec++; |
3227 | - cerr << "\t\tTest Failed: Answer should be " << val << endl; |
3228 | + ec++; |
3229 | + cerr << "\t\tTest Failed: Answer should be " << val << endl; |
3230 | } |
3231 | return ec; |
3232 | }; |
3233 | |
3234 | int main() |
3235 | { |
3236 | - ld_triad a(1,2,3); |
3237 | - ld_triad b(3,2,1); |
3238 | - int returnme = 0; |
3239 | + ld_triad a(1,2,3); |
3240 | + ld_triad b(3,2,1); |
3241 | + int returnme = 0; |
3242 | |
3243 | - cout << setprecision(10); |
3244 | - cout << "=== nrtb::triad Unit Test ===" << endl; |
3245 | - cout << "\ta = " << a << "; b = " << b << endl; |
3246 | - // basic operations tests |
3247 | - returnme = test_triad("a + b",a + b,ld_triad(4,4,4),returnme); |
3248 | - returnme = test_triad("a - b",a - b,ld_triad(-2,0,2),returnme); |
3249 | - returnme = test_triad("a * b",a * b,ld_triad(3,4,3),returnme); |
3250 | - returnme = test_triad("a / b",a / b,ld_triad(1.0d/(long double) 3.0,1,3),returnme); |
3251 | - returnme = test_triad("a += b; a",a += b,ld_triad(4,4,4),returnme); |
3252 | - returnme = test_triad("a -= b; a",a -= b,ld_triad(1,2,3),returnme); |
3253 | - returnme = test_triad("a *= b; a",a *= b,ld_triad(3,4,3),returnme); |
3254 | - returnme = test_triad("a /= b; a",a /= b,ld_triad(1,2,3),returnme); |
3255 | - // power test |
3256 | - returnme = test_triad("a.pow(b)",a.pow(b),ld_triad(1,4,3),returnme); |
3257 | - // range test |
3258 | - ld_triad t = b - a; |
3259 | - t *= t; |
3260 | - long double r = sqrt(t.x + t.y + t.z); |
3261 | - returnme = test_ld("a.range(b)",a.range(b),r,returnme); |
3262 | - // magnatude test |
3263 | - returnme = test_ld("a.magnatude()",a.magnatude(),a.range(0),returnme); |
3264 | - // boolean tests |
3265 | - returnme = test_ld("a == a",a == a,1,returnme); |
3266 | - returnme = test_ld("a == b",a == b,0,returnme); |
3267 | - returnme = test_ld("a != b",a != b,1,returnme); |
3268 | - returnme = test_ld("a != a",a != a,0,returnme); |
3269 | - // point/scalar operations |
3270 | - returnme = test_triad("a + 2",a + 2,ld_triad(3,4,5),returnme); |
3271 | - returnme = test_triad("a - 2",a - 2,ld_triad(-1,0,1),returnme); |
3272 | - returnme = test_triad("a * 2",a * 2,ld_triad(2,4,6),returnme); |
3273 | - returnme = test_triad("a / 2",a / 2,ld_triad(0.5,1,1.5),returnme); |
3274 | - returnme = test_triad("a += 2",a += 2,ld_triad(3,4,5),returnme); |
3275 | - returnme = test_triad("a -= 2",a -= 2,ld_triad(1,2,3),returnme); |
3276 | - returnme = test_triad("a *= 2",a *= 2,ld_triad(2,4,6),returnme); |
3277 | - returnme = test_triad("a /= 2",a /= 2,ld_triad(1,2,3),returnme); |
3278 | - returnme = test_triad("a.pow(2)",a.pow(2),ld_triad(1,4,9),returnme); |
3279 | - // normalization test |
3280 | - cout << "\ta.normalize() = " << a.normalize() << endl; |
3281 | - returnme = test_ld("a.normalize().magnatude()",a.normalize().magnatude(),1.0,returnme); |
3282 | - // dot and vector product tests. |
3283 | - returnme = test_ld("a.dot_product(b)",a.dot_product(b),10,returnme); |
3284 | - returnme = test_triad("a.vector_product(b)",a.vector_product(b), |
3285 | - ld_triad(-4,8,-4),returnme); |
3286 | - // string i/o tests, assumes "2,3.5,7) is input. |
3287 | - cout << "\tInput a new value for b \"(2,3.5,7)\": " << flush; |
3288 | - cin >> b; cout << endl; |
3289 | - returnme = test_triad("b",b,ld_triad(2,3.5,7),returnme); |
3290 | - returnme = test_triad("b.from_str(b.to_str(10))", |
3291 | - b.from_str(b.to_str(10)),ld_triad(2,3.5,7),returnme); |
3292 | - // report errors, if any |
3293 | - if (returnme) |
3294 | - { |
3295 | - cerr << "There were " << returnme |
3296 | - << " error(s) found." << endl; |
3297 | - } |
3298 | - cout << "=== nrtb::triad Unit Test Complete ===" << endl; |
3299 | - // return the error count as the exit code |
3300 | - return returnme; |
3301 | + cout << setprecision(10); |
3302 | + cout << "=== nrtb::triad Unit Test ===" << endl; |
3303 | + cout << "\ta = " << a << "; b = " << b << endl; |
3304 | + // basic operations tests |
3305 | + returnme = test_triad("a + b",a + b,ld_triad(4,4,4),returnme); |
3306 | + returnme = test_triad("a - b",a - b,ld_triad(-2,0,2),returnme); |
3307 | + returnme = test_triad("a * b",a * b,ld_triad(3,4,3),returnme); |
3308 | + returnme = test_triad("a / b",a / b,ld_triad(1.0d/(long double) 3.0,1,3),returnme); |
3309 | + returnme = test_triad("a += b; a",a += b,ld_triad(4,4,4),returnme); |
3310 | + returnme = test_triad("a -= b; a",a -= b,ld_triad(1,2,3),returnme); |
3311 | + returnme = test_triad("a *= b; a",a *= b,ld_triad(3,4,3),returnme); |
3312 | + returnme = test_triad("a /= b; a",a /= b,ld_triad(1,2,3),returnme); |
3313 | + // power test |
3314 | + returnme = test_triad("a.pow(b)",a.pow(b),ld_triad(1,4,3),returnme); |
3315 | + // range test |
3316 | + ld_triad t = b - a; |
3317 | + t *= t; |
3318 | + long double r = sqrt(t.x + t.y + t.z); |
3319 | + returnme = test_ld("a.range(b)",a.range(b),r,returnme); |
3320 | + // magnatude test |
3321 | + returnme = test_ld("a.magnatude()",a.magnatude(),a.range(0),returnme); |
3322 | + // boolean tests |
3323 | + returnme = test_ld("a == a",a == a,1,returnme); |
3324 | + returnme = test_ld("a == b",a == b,0,returnme); |
3325 | + returnme = test_ld("a != b",a != b,1,returnme); |
3326 | + returnme = test_ld("a != a",a != a,0,returnme); |
3327 | + // point/scalar operations |
3328 | + returnme = test_triad("a + 2",a + 2,ld_triad(3,4,5),returnme); |
3329 | + returnme = test_triad("a - 2",a - 2,ld_triad(-1,0,1),returnme); |
3330 | + returnme = test_triad("a * 2",a * 2,ld_triad(2,4,6),returnme); |
3331 | + returnme = test_triad("a / 2",a / 2,ld_triad(0.5,1,1.5),returnme); |
3332 | + returnme = test_triad("a += 2",a += 2,ld_triad(3,4,5),returnme); |
3333 | + returnme = test_triad("a -= 2",a -= 2,ld_triad(1,2,3),returnme); |
3334 | + returnme = test_triad("a *= 2",a *= 2,ld_triad(2,4,6),returnme); |
3335 | + returnme = test_triad("a /= 2",a /= 2,ld_triad(1,2,3),returnme); |
3336 | + returnme = test_triad("a.pow(2)",a.pow(2),ld_triad(1,4,9),returnme); |
3337 | + // normalization test |
3338 | + cout << "\ta.normalize() = " << a.normalize() << endl; |
3339 | + returnme = test_ld("a.normalize().magnatude()",a.normalize().magnatude(),1.0,returnme); |
3340 | + // dot and vector product tests. |
3341 | + returnme = test_ld("a.dot_product(b)",a.dot_product(b),10,returnme); |
3342 | + returnme = test_triad("a.vector_product(b)",a.vector_product(b), |
3343 | + ld_triad(-4,8,-4),returnme); |
3344 | + // string i/o tests, assumes "2,3.5,7) is input. |
3345 | + cout << "\tInput a new value for b \"(2,3.5,7)\": " << flush; |
3346 | + cin >> b; cout << endl; |
3347 | + returnme = test_triad("b",b,ld_triad(2,3.5,7),returnme); |
3348 | + returnme = test_triad("b.from_str(b.to_str(10))", |
3349 | + b.from_str(b.to_str(10)),ld_triad(2,3.5,7),returnme); |
3350 | + // report errors, if any |
3351 | + if (returnme) |
3352 | + { |
3353 | + cerr << "There were " << returnme |
3354 | + << " error(s) found." << endl; |
3355 | + } |
3356 | + cout << "=== nrtb::triad Unit Test Complete ===" << endl; |
3357 | + // return the error count as the exit code |
3358 | + return returnme; |
3359 | |
3360 | }; |
3361 | |
3362 | === modified file 'cpp/common/point/triad.h' |
3363 | --- obsolete/Cpp/common/point/triad.h 2011-07-27 02:27:23 +0000 |
3364 | +++ cpp/common/point/triad.h 2013-08-09 21:47:12 +0000 |
3365 | @@ -43,265 +43,265 @@ |
3366 | template <class T> |
3367 | struct triad |
3368 | { |
3369 | - /// X coordinate |
3370 | - T x; |
3371 | - /// Y coordinate |
3372 | - T y; |
3373 | - /// Z coordinate |
3374 | - T z; |
3375 | + /// X coordinate |
3376 | + T x; |
3377 | + /// Y coordinate |
3378 | + T y; |
3379 | + /// Z coordinate |
3380 | + T z; |
3381 | |
3382 | - /** Constructor. |
3383 | - ** |
3384 | - ** An easy way to create a point at the origin would be |
3385 | - ** "triad<T> a;". |
3386 | - **/ |
3387 | - triad(T _x=0, T _y=0, T _z=0); |
3388 | - triad<T> operator + (const triad<T> & a); |
3389 | - triad<T> operator - (const triad<T> & a); |
3390 | - triad<T> operator * (const triad<T> & a); |
3391 | - triad<T> operator / (const triad<T> & a); |
3392 | - triad<T> operator += (const triad<T> & a); |
3393 | - triad<T> operator -= (const triad<T> & a); |
3394 | - triad<T> operator *= (const triad<T> & a); |
3395 | - triad<T> operator /= (const triad<T> & a); |
3396 | - /// returns (pow(x,a.x),pow(y,a.y),pow(z,a.z)). |
3397 | - triad<T> pow(const triad<T> & a); |
3398 | - triad<T> operator + (const T & a); |
3399 | - triad<T> operator - (const T & a); |
3400 | - triad<T> operator * (const T & a); |
3401 | - triad<T> operator / (const T & a); |
3402 | - triad<T> operator += (const T & a); |
3403 | - triad<T> operator -= (const T & a); |
3404 | - triad<T> operator *= (const T & a); |
3405 | - triad<T> operator /= (const T & a); |
3406 | - /// returns (pow(x,a),pow(y,a),pow(z,a)). |
3407 | - triad<T> pow(const T & a); |
3408 | - /** Returns a normalized version of the triad. |
3409 | - ** |
3410 | - ** Normalization in this case refers to an operation resulting in a |
3411 | - ** traid where the magnatude of the vector is 1.0 while maintaining the |
3412 | - ** same angular component. For example, given triad<float> a = (1,2,3), |
3413 | - ** a.normalize() = (0.267,0.534,0.802). Of course, the original triad |
3414 | - ** is not modified. |
3415 | - ** |
3416 | - ** Normalized triads are very useful when calcuating force or |
3417 | - ** accelleration vectors, for example. |
3418 | - **/ |
3419 | - triad<T> normalize(); |
3420 | - /// Returns the distance between *this and the supplied argument. |
3421 | - T range(const triad<T> & a); |
3422 | - /// Returns the magnatude of the vector. |
3423 | - T magnatude(); |
3424 | - /// Returns the dot (scalar) product of two triads |
3425 | - T dot_product(const triad<T> & a); |
3426 | - /// Returns the vector product of two triads |
3427 | - triad<T> vector_product(const triad<T> & a); |
3428 | - bool operator == (const triad<T> & a); |
3429 | - bool operator != (const triad<T> & a); |
3430 | - /// Loads from a std::string. |
3431 | - triad<T> from_str(const std::string & a); |
3432 | - /// Returns a std::string representation. |
3433 | - std::string to_str(int precision=6); |
3434 | + /** Constructor. |
3435 | + ** |
3436 | + ** An easy way to create a point at the origin would be |
3437 | + ** "triad<T> a;". |
3438 | + **/ |
3439 | + triad(T _x=0, T _y=0, T _z=0); |
3440 | + triad<T> operator + (const triad<T> & a); |
3441 | + triad<T> operator - (const triad<T> & a); |
3442 | + triad<T> operator * (const triad<T> & a); |
3443 | + triad<T> operator / (const triad<T> & a); |
3444 | + triad<T> operator += (const triad<T> & a); |
3445 | + triad<T> operator -= (const triad<T> & a); |
3446 | + triad<T> operator *= (const triad<T> & a); |
3447 | + triad<T> operator /= (const triad<T> & a); |
3448 | + /// returns (pow(x,a.x),pow(y,a.y),pow(z,a.z)). |
3449 | + triad<T> pow(const triad<T> & a); |
3450 | + triad<T> operator + (const T & a); |
3451 | + triad<T> operator - (const T & a); |
3452 | + triad<T> operator * (const T & a); |
3453 | + triad<T> operator / (const T & a); |
3454 | + triad<T> operator += (const T & a); |
3455 | + triad<T> operator -= (const T & a); |
3456 | + triad<T> operator *= (const T & a); |
3457 | + triad<T> operator /= (const T & a); |
3458 | + /// returns (pow(x,a),pow(y,a),pow(z,a)). |
3459 | + triad<T> pow(const T & a); |
3460 | + /** Returns a normalized version of the triad. |
3461 | + ** |
3462 | + ** Normalization in this case refers to an operation resulting in a |
3463 | + ** traid where the magnatude of the vector is 1.0 while maintaining the |
3464 | + ** same angular component. For example, given triad<float> a = (1,2,3), |
3465 | + ** a.normalize() = (0.267,0.534,0.802). Of course, the original triad |
3466 | + ** is not modified. |
3467 | + ** |
3468 | + ** Normalized triads are very useful when calcuating force or |
3469 | + ** accelleration vectors, for example. |
3470 | + **/ |
3471 | + triad<T> normalize(); |
3472 | + /// Returns the distance between *this and the supplied argument. |
3473 | + T range(const triad<T> & a); |
3474 | + /// Returns the magnatude of the vector. |
3475 | + T magnatude(); |
3476 | + /// Returns the dot (scalar) product of two triads |
3477 | + T dot_product(const triad<T> & a); |
3478 | + /// Returns the vector product of two triads |
3479 | + triad<T> vector_product(const triad<T> & a); |
3480 | + bool operator == (const triad<T> & a); |
3481 | + bool operator != (const triad<T> & a); |
3482 | + /// Loads from a std::string. |
3483 | + triad<T> from_str(const std::string & a); |
3484 | + /// Returns a std::string representation. |
3485 | + std::string to_str(int precision=6); |
3486 | }; |
3487 | |
3488 | template <class T> |
3489 | triad<T>::triad(T _x, T _y, T _z) |
3490 | { |
3491 | - x = _x; |
3492 | - y = _y; |
3493 | - z = _z; |
3494 | + x = _x; |
3495 | + y = _y; |
3496 | + z = _z; |
3497 | }; |
3498 | |
3499 | template <class T> |
3500 | triad<T> triad<T>::operator + (const triad<T> & a) |
3501 | { |
3502 | - triad<T> returnme; |
3503 | - returnme.x = x + a.x; |
3504 | - returnme.y = y + a.y; |
3505 | - returnme.z = z + a.z; |
3506 | - return returnme; |
3507 | + triad<T> returnme; |
3508 | + returnme.x = x + a.x; |
3509 | + returnme.y = y + a.y; |
3510 | + returnme.z = z + a.z; |
3511 | + return returnme; |
3512 | }; |
3513 | |
3514 | template <class T> |
3515 | triad<T> triad<T>::operator - (const triad<T> & a) |
3516 | { |
3517 | - triad<T> returnme; |
3518 | - returnme.x = x - a.x; |
3519 | - returnme.y = y - a.y; |
3520 | - returnme.z = z - a.z; |
3521 | - return returnme; |
3522 | + triad<T> returnme; |
3523 | + returnme.x = x - a.x; |
3524 | + returnme.y = y - a.y; |
3525 | + returnme.z = z - a.z; |
3526 | + return returnme; |
3527 | }; |
3528 | |
3529 | template <class T> |
3530 | triad<T> triad<T>::operator * (const triad<T> & a) |
3531 | { |
3532 | - triad<T> returnme; |
3533 | - returnme.x = x * a.x; |
3534 | - returnme.y = y * a.y; |
3535 | - returnme.z = z * a.z; |
3536 | - return returnme; |
3537 | + triad<T> returnme; |
3538 | + returnme.x = x * a.x; |
3539 | + returnme.y = y * a.y; |
3540 | + returnme.z = z * a.z; |
3541 | + return returnme; |
3542 | }; |
3543 | |
3544 | template <class T> |
3545 | triad<T> triad<T>::operator / (const triad<T> & a) |
3546 | { |
3547 | - triad<T> returnme; |
3548 | - returnme.x = x / a.x; |
3549 | - returnme.y = y / a.y; |
3550 | - returnme.z = z / a.z; |
3551 | - return returnme; |
3552 | + triad<T> returnme; |
3553 | + returnme.x = x / a.x; |
3554 | + returnme.y = y / a.y; |
3555 | + returnme.z = z / a.z; |
3556 | + return returnme; |
3557 | }; |
3558 | |
3559 | template <class T> |
3560 | triad<T> triad<T>::operator += (const triad<T> & a) |
3561 | { |
3562 | - x += a.x; |
3563 | - y += a.y; |
3564 | - z += a.z; |
3565 | - return *this; |
3566 | + x += a.x; |
3567 | + y += a.y; |
3568 | + z += a.z; |
3569 | + return *this; |
3570 | }; |
3571 | |
3572 | template <class T> |
3573 | triad<T> triad<T>::operator -= (const triad<T> & a) |
3574 | { |
3575 | - x -= a.x; |
3576 | - y -= a.y; |
3577 | - z -= a.z; |
3578 | - return *this; |
3579 | + x -= a.x; |
3580 | + y -= a.y; |
3581 | + z -= a.z; |
3582 | + return *this; |
3583 | }; |
3584 | |
3585 | template <class T> |
3586 | triad<T> triad<T>::operator *= (const triad<T> & a) |
3587 | { |
3588 | - x *= a.x; |
3589 | - y *= a.y; |
3590 | - z *= a.z; |
3591 | - return *this; |
3592 | + x *= a.x; |
3593 | + y *= a.y; |
3594 | + z *= a.z; |
3595 | + return *this; |
3596 | }; |
3597 | |
3598 | template <class T> |
3599 | triad<T> triad<T>::operator /= (const triad<T> & a) |
3600 | { |
3601 | - x /= a.x; |
3602 | - y /= a.y; |
3603 | - z /= a.z; |
3604 | - return *this; |
3605 | + x /= a.x; |
3606 | + y /= a.y; |
3607 | + z /= a.z; |
3608 | + return *this; |
3609 | }; |
3610 | |
3611 | template <class T> |
3612 | triad<T> triad<T>::pow(const triad<T> & a) |
3613 | { |
3614 | - triad<T> returnme; |
3615 | - returnme.x = ::pow(x,a.x); |
3616 | - returnme.y = ::pow(y,a.y); |
3617 | - returnme.z = ::pow(z,a.z); |
3618 | - return returnme; |
3619 | + triad<T> returnme; |
3620 | + returnme.x = ::pow(x,a.x); |
3621 | + returnme.y = ::pow(y,a.y); |
3622 | + returnme.z = ::pow(z,a.z); |
3623 | + return returnme; |
3624 | }; |
3625 | |
3626 | template <class T> |
3627 | triad<T> triad<T>::normalize() |
3628 | { |
3629 | - return (*this / this->magnatude()); |
3630 | + return (*this / this->magnatude()); |
3631 | }; |
3632 | |
3633 | template <class T> |
3634 | triad<T> triad<T>::operator + (const T & a) |
3635 | { |
3636 | - triad<T> returnme; |
3637 | - returnme.x = x + a; |
3638 | - returnme.y = y + a; |
3639 | - returnme.z = z + a; |
3640 | - return returnme; |
3641 | + triad<T> returnme; |
3642 | + returnme.x = x + a; |
3643 | + returnme.y = y + a; |
3644 | + returnme.z = z + a; |
3645 | + return returnme; |
3646 | }; |
3647 | |
3648 | template <class T> |
3649 | triad<T> triad<T>::operator - (const T & a) |
3650 | { |
3651 | - triad<T> returnme; |
3652 | - returnme.x = x - a; |
3653 | - returnme.y = y - a; |
3654 | - returnme.z = z - a; |
3655 | - return returnme; |
3656 | + triad<T> returnme; |
3657 | + returnme.x = x - a; |
3658 | + returnme.y = y - a; |
3659 | + returnme.z = z - a; |
3660 | + return returnme; |
3661 | }; |
3662 | |
3663 | template <class T> |
3664 | triad<T> triad<T>::operator * (const T & a) |
3665 | { |
3666 | - triad<T> returnme; |
3667 | - returnme.x = x * a; |
3668 | - returnme.y = y * a; |
3669 | - returnme.z = z * a; |
3670 | - return returnme; |
3671 | + triad<T> returnme; |
3672 | + returnme.x = x * a; |
3673 | + returnme.y = y * a; |
3674 | + returnme.z = z * a; |
3675 | + return returnme; |
3676 | }; |
3677 | |
3678 | template <class T> |
3679 | triad<T> triad<T>::operator / (const T & a) |
3680 | { |
3681 | - triad<T> returnme; |
3682 | - returnme.x = x / a; |
3683 | - returnme.y = y / a; |
3684 | - returnme.z = z / a; |
3685 | - return returnme; |
3686 | + triad<T> returnme; |
3687 | + returnme.x = x / a; |
3688 | + returnme.y = y / a; |
3689 | + returnme.z = z / a; |
3690 | + return returnme; |
3691 | }; |
3692 | |
3693 | template <class T> |
3694 | triad<T> triad<T>::operator += (const T & a) |
3695 | { |
3696 | - x += a; |
3697 | - y += a; |
3698 | - z += a; |
3699 | - return *this; |
3700 | + x += a; |
3701 | + y += a; |
3702 | + z += a; |
3703 | + return *this; |
3704 | }; |
3705 | |
3706 | template <class T> |
3707 | triad<T> triad<T>::operator -= (const T & a) |
3708 | { |
3709 | - x -= a; |
3710 | - y -= a; |
3711 | - z -= a; |
3712 | - return *this; |
3713 | + x -= a; |
3714 | + y -= a; |
3715 | + z -= a; |
3716 | + return *this; |
3717 | }; |
3718 | |
3719 | template <class T> |
3720 | triad<T> triad<T>::operator *= (const T & a) |
3721 | { |
3722 | - x *= a; |
3723 | - y *= a; |
3724 | - z *= a; |
3725 | - return *this; |
3726 | + x *= a; |
3727 | + y *= a; |
3728 | + z *= a; |
3729 | + return *this; |
3730 | }; |
3731 | |
3732 | template <class T> |
3733 | triad<T> triad<T>::operator /= (const T & a) |
3734 | { |
3735 | - x /= a; |
3736 | - y /= a; |
3737 | - z /= a; |
3738 | - return *this; |
3739 | + x /= a; |
3740 | + y /= a; |
3741 | + z /= a; |
3742 | + return *this; |
3743 | }; |
3744 | |
3745 | template <class T> |
3746 | triad<T> triad<T>::pow(const T & a) |
3747 | { |
3748 | - triad<T> returnme; |
3749 | - returnme.x = ::pow(x,a); |
3750 | - returnme.y = ::pow(y,a); |
3751 | - returnme.z = ::pow(z,a); |
3752 | - return returnme; |
3753 | + triad<T> returnme; |
3754 | + returnme.x = ::pow(x,a); |
3755 | + returnme.y = ::pow(y,a); |
3756 | + returnme.z = ::pow(z,a); |
3757 | + return returnme; |
3758 | }; |
3759 | |
3760 | template <class T> |
3761 | T triad<T>::range(const triad<T> & a) |
3762 | { |
3763 | - triad<T> offset = *this - a; |
3764 | - offset *= offset; |
3765 | - return sqrt(offset.x + offset.y + offset.z); |
3766 | + triad<T> offset = *this - a; |
3767 | + offset *= offset; |
3768 | + return sqrt(offset.x + offset.y + offset.z); |
3769 | }; |
3770 | |
3771 | template <class T> |
3772 | T triad<T>::magnatude() |
3773 | { |
3774 | - return sqrt((x*x) + (y*y) + (z*z)); |
3775 | + return sqrt((x*x) + (y*y) + (z*z)); |
3776 | }; |
3777 | |
3778 | template <class T> |
3779 | @@ -327,39 +327,39 @@ |
3780 | template <class T> |
3781 | bool triad<T>::operator == (const triad<T> & a) |
3782 | { |
3783 | - return ((x == a.x) && (y == a.y) && (z == a.z)); |
3784 | + return ((x == a.x) && (y == a.y) && (z == a.z)); |
3785 | }; |
3786 | |
3787 | template <class T> |
3788 | bool triad<T>::operator != (const triad<T> & a) |
3789 | { |
3790 | - return (! (*this == a)); |
3791 | + return (! (*this == a)); |
3792 | }; |
3793 | |
3794 | template <class T> |
3795 | triad<T> triad<T>::from_str(const std::string & a) |
3796 | { |
3797 | - std::istringstream t(a.c_str()); |
3798 | - t >> *this; |
3799 | - return *this; |
3800 | + std::istringstream t(a.c_str()); |
3801 | + t >> *this; |
3802 | + return *this; |
3803 | }; |
3804 | |
3805 | template <class T> |
3806 | std::string triad<T>::to_str(int precision) |
3807 | { |
3808 | - std::stringstream a; |
3809 | - a << std::setprecision(precision) << *this; |
3810 | - std::string returnme; |
3811 | - a >> returnme; |
3812 | - return returnme; |
3813 | + std::stringstream a; |
3814 | + a << std::setprecision(precision) << *this; |
3815 | + std::string returnme; |
3816 | + a >> returnme; |
3817 | + return returnme; |
3818 | }; |
3819 | |
3820 | /// Writes the triad<T> in the format "(x,y,z)" to the output stream. |
3821 | template <class T> |
3822 | std::ostream & operator << (std::ostream &f, const triad<T> & a) |
3823 | { |
3824 | - f << "(" << a.x << "," << a.y << "," << a.z << ")"; |
3825 | - return f; |
3826 | + f << "(" << a.x << "," << a.y << "," << a.z << ")"; |
3827 | + return f; |
3828 | }; |
3829 | |
3830 | /** Reads the triad<T> from an input stream. |
3831 | @@ -372,22 +372,22 @@ |
3832 | template <class T> |
3833 | std::istream & operator >> (std::istream &f, triad<T> & a) |
3834 | { |
3835 | - std::string element; |
3836 | - f >> element; |
3837 | - strlist t = split(element,','); |
3838 | - if (t.size() != 3) |
3839 | - { |
3840 | - a = 0; |
3841 | - } |
3842 | - else |
3843 | - { |
3844 | - std::stringstream transmorgrafier; |
3845 | - transmorgrafier << std::setprecision(30); |
3846 | - if (t[0][0] == '(') { t[0].erase(0,1); }; |
3847 | - for(int i=0; i < 3; i++) { transmorgrafier << t[i] << " "; }; |
3848 | - transmorgrafier >> a.x >> a.y >> a.z; |
3849 | - }; |
3850 | - return f; |
3851 | + std::string element; |
3852 | + f >> element; |
3853 | + strlist t = split(element,','); |
3854 | + if (t.size() != 3) |
3855 | + { |
3856 | + a = 0; |
3857 | + } |
3858 | + else |
3859 | + { |
3860 | + std::stringstream transmorgrafier; |
3861 | + transmorgrafier << std::setprecision(30); |
3862 | + if (t[0][0] == '(') { t[0].erase(0,1); }; |
3863 | + for(int i=0; i < 3; i++) { transmorgrafier << t[i] << " "; }; |
3864 | + transmorgrafier >> a.x >> a.y >> a.z; |
3865 | + }; |
3866 | + return f; |
3867 | }; |
3868 | |
3869 | } // namespace nrtb |
3870 | |
3871 | === modified file 'cpp/common/serializer/Makefile' |
3872 | --- obsolete/Cpp/common/serializer/Makefile 2012-04-06 17:44:53 +0000 |
3873 | +++ cpp/common/serializer/Makefile 2013-08-09 21:47:12 +0000 |
3874 | @@ -28,8 +28,8 @@ |
3875 | |
3876 | serializer_test: serializer.o serializer_test.cpp |
3877 | @rm -f serializer_test |
3878 | - g++ -c serializer_test.cpp -I../include -std=gnu++0x |
3879 | - g++ -o serializer_test serializer_test.o serializer.o ../obj/base_thread.o -lpthread ../obj/common.o -std=gnu++0x |
3880 | + g++ -c serializer_test.cpp -I../include -std=gnu++11 |
3881 | + g++ -o serializer_test serializer_test.o serializer.o -lpthread -std=gnu++11 |
3882 | |
3883 | clean: |
3884 | @rm -rvf *.o serializer_test ../include/serializer.h ../obj/serializer.o |
3885 | |
3886 | === modified file 'cpp/common/serializer/serializer.cpp' |
3887 | --- obsolete/Cpp/common/serializer/serializer.cpp 2011-07-30 15:32:43 +0000 |
3888 | +++ cpp/common/serializer/serializer.cpp 2013-08-09 21:47:12 +0000 |
3889 | @@ -17,7 +17,6 @@ |
3890 | **********************************************/ |
3891 | |
3892 | #include "serializer.h" |
3893 | -#include <base_thread.h> |
3894 | |
3895 | using namespace nrtb; |
3896 | |
3897 | @@ -38,6 +37,5 @@ |
3898 | |
3899 | unsigned long long serializer::operator()() |
3900 | { |
3901 | - nrtb::scope_lock mylock(lock); |
3902 | return counter++; |
3903 | } |
3904 | |
3905 | === modified file 'cpp/common/serializer/serializer.h' |
3906 | --- obsolete/Cpp/common/serializer/serializer.h 2011-09-15 01:21:11 +0000 |
3907 | +++ cpp/common/serializer/serializer.h 2013-08-09 21:47:12 +0000 |
3908 | @@ -18,7 +18,8 @@ |
3909 | |
3910 | #ifndef nrtb_serializer_h |
3911 | #define nrtb_serializer_h |
3912 | -#include <base_thread.h> |
3913 | + |
3914 | +#include <atomic> |
3915 | |
3916 | namespace nrtb |
3917 | { |
3918 | @@ -41,8 +42,7 @@ |
3919 | // functor method, returns the next value in the sequence. |
3920 | unsigned long long operator ()(); |
3921 | private: |
3922 | - nrtb::mutex lock; |
3923 | - unsigned long long int counter; |
3924 | + std::atomic<unsigned long long> counter; |
3925 | }; |
3926 | |
3927 | } |
3928 | |
3929 | === modified file 'cpp/common/singleton/Makefile' |
3930 | --- obsolete/Cpp/common/singleton/Makefile 2012-04-06 17:46:15 +0000 |
3931 | +++ cpp/common/singleton/Makefile 2013-08-09 21:47:12 +0000 |
3932 | @@ -16,6 +16,7 @@ |
3933 | # |
3934 | #*********************************************** |
3935 | |
3936 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
3937 | |
3938 | lib: singleton_test |
3939 | @./singleton_test |
3940 | @@ -24,8 +25,8 @@ |
3941 | |
3942 | singleton_test: singleton_test.cpp Makefile |
3943 | @rm -f singleton_test |
3944 | - g++ -c singleton_test.cpp -I ../include -std=gnu++0x |
3945 | - g++ -o singleton_test singleton_test.o ../obj/base_thread.o ../obj/common.o ../obj/serializer.o -lpthread -std=gnu++0x |
3946 | + g++ -c singleton_test.cpp -I ../include ${switches} |
3947 | + g++ -o singleton_test singleton_test.o ../obj/serializer.o -lpthread ${switches} |
3948 | |
3949 | clean: |
3950 | @rm -rvf *.o singleton_test ../include/singleton.h |
3951 | |
3952 | === modified file 'cpp/common/singleton/singleton.h' |
3953 | --- obsolete/Cpp/common/singleton/singleton.h 2011-08-13 13:13:25 +0000 |
3954 | +++ cpp/common/singleton/singleton.h 2013-08-09 21:47:12 +0000 |
3955 | @@ -25,7 +25,9 @@ |
3956 | #ifndef nrtb_singleton_h |
3957 | #define nrtb_singleton_h |
3958 | |
3959 | -#include <base_thread.h> |
3960 | +#include <mutex> |
3961 | +#include <memory> |
3962 | +#include <atomic> |
3963 | |
3964 | namespace nrtb |
3965 | { |
3966 | @@ -55,68 +57,70 @@ |
3967 | template <class T, int mytag=0> |
3968 | class singleton: public T |
3969 | { |
3970 | - private: |
3971 | - static mutex __mylock; |
3972 | - static singleton * __me; |
3973 | - protected: |
3974 | - singleton() : T() {}; |
3975 | - virtual ~singleton() {}; |
3976 | - singleton(const singleton &) {}; |
3977 | - public: |
3978 | - /** Used to access the object. |
3979 | - ** |
3980 | - ** Returns a reference to the instanciated singleton object. If |
3981 | - ** the object has not been accessed before, the object will be |
3982 | - ** instanciated automatically. |
3983 | - ** |
3984 | - ** As is usual for the method that provides access to a singleton, |
3985 | - ** this method is static, allowing it to be called via the class |
3986 | - ** name as shown. Remember you can only assign the return value to |
3987 | - ** a reference: |
3988 | - ** |
3989 | - ** mytype & a = mytype::get_instance(); |
3990 | - ** |
3991 | - ** Attempts to make a copy of the instance should throw a compiler |
3992 | - ** error. |
3993 | - ** |
3994 | - ** This method is thread safe, but that does not imply that the |
3995 | - ** class returned is thread-safe overall; that would depend on the |
3996 | - ** implementation of the class used to instaciate the template. |
3997 | - **/ |
3998 | - static singleton & get_instance() |
3999 | - { |
4000 | - // First test avoids expensive mutex cycle |
4001 | - // if the object is already allocated. |
4002 | - if (!__me) |
4003 | - { |
4004 | - scope_lock lock(__mylock); |
4005 | - // second test required in case multiple threads |
4006 | - // get past the first check. |
4007 | - if (!__me) |
4008 | - { |
4009 | - __me = new singleton; |
4010 | - }; |
4011 | - }; |
4012 | - return *__me; |
4013 | - }; |
4014 | +private: |
4015 | + static std::mutex __mylock; |
4016 | + static singleton<T,mytag> * __me ; |
4017 | +protected: |
4018 | + singleton() : T() {}; |
4019 | + virtual ~singleton() {}; |
4020 | + singleton(const singleton &) = delete; |
4021 | +public: |
4022 | + /** Used to access the object. |
4023 | + ** |
4024 | + ** Returns a reference to the instanciated singleton object. If |
4025 | + ** the object has not been accessed before, the object will be |
4026 | + ** instanciated automatically. |
4027 | + ** |
4028 | + ** As is usual for the method that provides access to a singleton, |
4029 | + ** this method is static, allowing it to be called via the class |
4030 | + ** name as shown. Remember you can only assign the return value to |
4031 | + ** a reference: |
4032 | + ** |
4033 | + ** mytype & a = mytype::get_instance(); |
4034 | + ** |
4035 | + ** Attempts to make a copy of the instance should throw a compiler |
4036 | + ** error. |
4037 | + ** |
4038 | + ** This method is thread safe, but that does not imply that the |
4039 | + ** class returned is thread-safe overall; that would depend on the |
4040 | + ** implementation of the class used to instaciate the template. |
4041 | + **/ |
4042 | + static singleton & get_reference() |
4043 | + { |
4044 | + // First test avoids expensive mutex cycle |
4045 | + // if the object is already allocated. |
4046 | + if (!__me) |
4047 | + { |
4048 | + std::unique_lock<std::mutex> lock(__mylock); |
4049 | + // second test required in case multiple threads |
4050 | + // get past the first check. |
4051 | + if (!__me) |
4052 | + { |
4053 | + __me = new singleton; |
4054 | + }; |
4055 | + }; |
4056 | + return *__me; |
4057 | + }; |
4058 | |
4059 | - /** Destructs and deallocates the singleton object. |
4060 | - ** |
4061 | - ** After a call to this method, the singleton object will |
4062 | - ** be destructed and deallocated from memory. However, it |
4063 | - ** will be automatically reconstruted and allocated if |
4064 | - ** get_instance() called at any time afterword. |
4065 | - **/ |
4066 | - void delete_me() |
4067 | - { |
4068 | - scope_lock lock(__mylock); |
4069 | - if (__me) delete __me; |
4070 | - __me = 0; |
4071 | - }; |
4072 | + /** Destructs and deallocates the singleton object. |
4073 | + ** |
4074 | + ** After a call to this method, the singleton object will |
4075 | + ** be destructed and deallocated from memory. However, it |
4076 | + ** will be automatically reconstruted and allocated if |
4077 | + ** get_instance() called at any time afterword. |
4078 | + **/ |
4079 | + void delete_me() |
4080 | + { |
4081 | + std::unique_lock<std::mutex> lock(__mylock); |
4082 | + if (__me) delete __me; |
4083 | + __me = 0; |
4084 | + }; |
4085 | }; |
4086 | |
4087 | -template <class T, int mytag> mutex singleton<T,mytag>::__mylock; |
4088 | -template <class T, int mytag> singleton<T,mytag> * singleton<T,mytag>::__me = 0; |
4089 | +template <class T, int mytag> |
4090 | + std::mutex singleton<T,mytag>::__mylock; |
4091 | +template <class T, int mytag> |
4092 | + singleton<T,mytag> * singleton<T,mytag>::__me; |
4093 | |
4094 | } // namespace nrtb; |
4095 | |
4096 | |
4097 | === modified file 'cpp/common/singleton/singleton_test.cpp' |
4098 | --- obsolete/Cpp/common/singleton/singleton_test.cpp 2011-08-13 14:19:56 +0000 |
4099 | +++ cpp/common/singleton/singleton_test.cpp 2013-08-09 21:47:12 +0000 |
4100 | @@ -32,24 +32,25 @@ |
4101 | |
4102 | cout << "============== singleton unit test ================" |
4103 | << endl; |
4104 | - int er_count = 0; |
4105 | + int er_count {0}; |
4106 | |
4107 | - sequence_type & a = sequence_type::get_instance(); |
4108 | + sequence_type & a = sequence_type::get_reference(); |
4109 | |
4110 | for (int i=0; i<10; i++) |
4111 | { |
4112 | - cout << a(); |
4113 | + cout << a(); |
4114 | }; |
4115 | |
4116 | - sequence_type & b = sequence_type::get_instance(); |
4117 | + sequence_type & b = sequence_type::get_reference(); |
4118 | |
4119 | if ( b() != 10) |
4120 | { |
4121 | - er_count++; |
4122 | + er_count++; |
4123 | }; |
4124 | |
4125 | - cout << "\n=========== singleton test " << (er_count ? "failed" : "passed") |
4126 | - << " =============" << endl; |
4127 | + cout << "\n=========== singleton test " |
4128 | + << (er_count ? "failed" : "passed") |
4129 | + << " =============" << endl; |
4130 | |
4131 | return er_count; |
4132 | }; |
4133 | |
4134 | === modified file 'cpp/common/sockets/Makefile' |
4135 | --- obsolete/Cpp/common/sockets/Makefile 2012-03-31 21:56:49 +0000 |
4136 | +++ cpp/common/sockets/Makefile 2013-08-09 21:47:12 +0000 |
4137 | @@ -16,6 +16,8 @@ |
4138 | # |
4139 | #*********************************************** |
4140 | |
4141 | +switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP |
4142 | + |
4143 | lib: socket_test |
4144 | @./socket_test |
4145 | @cp -v base_socket.h ../include/ |
4146 | @@ -24,13 +26,13 @@ |
4147 | |
4148 | socket_test: base_socket.o socket_test.cpp |
4149 | @rm -f socket_test |
4150 | - g++ -c -O3 socket_test.cpp -I ../include -std=gnu++0x |
4151 | - g++ -o socket_test socket_test.o base_socket.o ../obj/hires_timer.o ../obj/common.o ../obj/base_thread.o -lpthread -std=gnu++0x |
4152 | + g++ -c -O3 socket_test.cpp -I ../include ${switches} |
4153 | + g++ -o socket_test socket_test.o base_socket.o ../obj/common.o -lpthread ${switches} |
4154 | |
4155 | |
4156 | base_socket.o: base_socket.cpp base_socket.h Makefile |
4157 | @rm -f base_socket.o |
4158 | - g++ -c -O3 base_socket.cpp -I ../include -std=gnu++0x |
4159 | + g++ -c -O3 base_socket.cpp -I ../include ${switches} |
4160 | |
4161 | clean: |
4162 | @rm -vf *.o ../include/base_socket.h socket_test |
4163 | |
4164 | === modified file 'cpp/common/sockets/base_socket.cpp' |
4165 | --- obsolete/Cpp/common/sockets/base_socket.cpp 2012-04-07 14:16:46 +0000 |
4166 | +++ cpp/common/sockets/base_socket.cpp 2013-08-09 21:47:12 +0000 |
4167 | @@ -19,11 +19,13 @@ |
4168 | // see base_socket.h for documentation |
4169 | |
4170 | #include "base_socket.h" |
4171 | +#include <boost/lexical_cast.hpp> |
4172 | #include <string.h> |
4173 | #include <errno.h> |
4174 | #include <arpa/inet.h> |
4175 | #include <netdb.h> |
4176 | -#include <boost/lexical_cast.hpp> |
4177 | +#include <vector> |
4178 | +#include <regex> |
4179 | |
4180 | // testing |
4181 | #include <iostream> |
4182 | @@ -34,554 +36,527 @@ |
4183 | namespace nrtb |
4184 | { |
4185 | |
4186 | -// added for Solaris 2.6 |
4187 | -#ifdef no_inet_aton |
4188 | -int inet_aton(const char * addr, in_addr * inp) |
4189 | -{ |
4190 | - // this workaround defines inet_aton in term in_addr. Drawbacks are |
4191 | - // that there is no useful error checking. |
4192 | - inp->s_addr = inet_addr(addr); |
4193 | - return (inp->s_addr != 0); |
4194 | -}; |
4195 | -#endif // no_inet_aton |
4196 | - |
4197 | -// added for solaris 2.6 |
4198 | -#ifdef no_socklen_t |
4199 | -typedef int socklen_t; |
4200 | -#endif // no_sock_len_t |
4201 | - |
4202 | int tcp_socket::transmit(const string & data) |
4203 | { |
4204 | - return send(mysock,data.c_str(),data.length(),MSG_DONTWAIT); |
4205 | + return send(mysock,data.c_str(),data.length(),MSG_DONTWAIT); |
4206 | }; |
4207 | |
4208 | int tcp_socket::receive(std::string & data, int limit) |
4209 | { |
4210 | - errno = 0; |
4211 | - data = ""; |
4212 | - // make more room in the input buffer if needed. |
4213 | - int bufsize = limit + 1; |
4214 | - if (bufsize > inbuff.size()) inbuff.resize(bufsize); |
4215 | - // get the data to inbuff |
4216 | - int returnme = recv(mysock,(void *) &(inbuff[0]),limit,0); |
4217 | - // did we get anything? |
4218 | - if (returnme > 0) |
4219 | - { |
4220 | - // yes.. store for the caller. |
4221 | - data.resize(returnme,0); |
4222 | - for (int i=0; i<returnme; i++) |
4223 | - { |
4224 | - data[i] = inbuff[i]; |
4225 | - }; |
4226 | - } |
4227 | - // ... or was there an error? |
4228 | - else if (errno) |
4229 | - { |
4230 | - // flag it for the caller. |
4231 | - returnme = -1; |
4232 | - }; |
4233 | - return returnme; |
4234 | + errno = 0; |
4235 | + data = ""; |
4236 | + // make more room in the input buffer if needed. |
4237 | + int bufsize = limit + 1; |
4238 | + if (bufsize > inbuff.size()) inbuff.resize(bufsize); |
4239 | + // get the data to inbuff |
4240 | + int returnme = recv(mysock,(void *) &(inbuff[0]),limit,0); |
4241 | + // did we get anything? |
4242 | + if (returnme > 0) |
4243 | + { |
4244 | + // yes.. store for the caller. |
4245 | + data.resize(returnme,0); |
4246 | + for (int i=0; i<returnme; i++) |
4247 | + { |
4248 | + data[i] = inbuff[i]; |
4249 | + }; |
4250 | + } |
4251 | + // ... or was there an error? |
4252 | + else if (errno) |
4253 | + { |
4254 | + // flag it for the caller. |
4255 | + returnme = -1; |
4256 | + }; |
4257 | + return returnme; |
4258 | }; |
4259 | |
4260 | tcp_socket::tcp_socket(bool autoclose) |
4261 | { |
4262 | - close_on_destruct = autoclose; |
4263 | - mysock = socket(AF_INET,SOCK_STREAM,0); |
4264 | - _status = sock_init; |
4265 | - _last_error = 0; |
4266 | + close_on_destruct = autoclose; |
4267 | + mysock = socket(AF_INET,SOCK_STREAM,0); |
4268 | + _status = state::sock_init; |
4269 | + _last_error = 0; |
4270 | }; |
4271 | |
4272 | tcp_socket::tcp_socket(int existing_socket, bool autoclose) |
4273 | { |
4274 | - close_on_destruct = autoclose; |
4275 | - mysock = existing_socket; |
4276 | - _status = sock_connect; |
4277 | - _last_error = 0; |
4278 | + close_on_destruct = autoclose; |
4279 | + mysock = existing_socket; |
4280 | + _status = state::sock_connect; |
4281 | + _last_error = 0; |
4282 | }; |
4283 | |
4284 | tcp_socket::~tcp_socket() |
4285 | { |
4286 | - if (close_on_destruct) |
4287 | - { |
4288 | - try {shutdown(mysock,SHUT_RDWR); } catch (...) {}; |
4289 | - try {::close(mysock); } catch (...) {}; |
4290 | - _status = sock_undef; |
4291 | - }; |
4292 | + if (close_on_destruct) |
4293 | + { |
4294 | + try {shutdown(mysock,SHUT_RDWR); } catch (...) {}; |
4295 | + try {::close(mysock); } catch (...) {}; |
4296 | + _status = state::sock_undef; |
4297 | + }; |
4298 | }; |
4299 | |
4300 | void tcp_socket::reset() |
4301 | { |
4302 | - // close the old socket if we can. |
4303 | - try { close(); } catch (tcp_socket::general_exception) {}; |
4304 | - // get a new one. |
4305 | - mysock = socket(AF_INET,SOCK_STREAM,0); |
4306 | - // set up the default conditions; |
4307 | - _status = sock_init; |
4308 | - _last_error = 0; |
4309 | + // close the old socket if we can. |
4310 | + try { close(); } catch (tcp_socket::general_exception) {} |
4311 | + // get a new one. |
4312 | + mysock = socket(AF_INET,SOCK_STREAM,0); |
4313 | + // set up the default conditions; |
4314 | + _status = state::sock_init; |
4315 | + _last_error = 0; |
4316 | }; |
4317 | |
4318 | sockaddr_in tcp_socket::str_to_sockaddr(const string & address) |
4319 | { |
4320 | - sockaddr_in in_address; |
4321 | - // init our address structure. |
4322 | - memset(&in_address,0,sizeof(in_address)); |
4323 | - //in_address.sin_len = 16; |
4324 | - in_address.sin_family = AF_INET; |
4325 | - // seperate the IP and port addresses. |
4326 | - const int IP = 0; |
4327 | - const int PORT = 1; |
4328 | - strlist addr; |
4329 | - addr = split(address,':'); |
4330 | - if (addr.size() != 2) |
4331 | - { |
4332 | - throw bad_address_exception(); |
4333 | - }; |
4334 | - if (addr[IP] != "*") |
4335 | - { |
4336 | - // first attempt name resolution |
4337 | - hostent * name = gethostbyname(addr[IP].c_str()); |
4338 | - if ((name != 0) && (name->h_length > 0)) |
4339 | - { |
4340 | - in_address.sin_addr = *( (in_addr *) (name->h_addr_list[0])); |
4341 | - } |
4342 | - else if (!inet_aton(addr[IP].c_str(),&in_address.sin_addr)) |
4343 | - { |
4344 | - throw bad_address_exception(); |
4345 | - }; |
4346 | - }; |
4347 | - if (addr[PORT] != "*") |
4348 | - { |
4349 | - // get the good port; |
4350 | - uint16_t port = lexical_cast<uint16_t>(addr[PORT]); |
4351 | - in_address.sin_port = htons(port); |
4352 | - }; |
4353 | - return in_address; |
4354 | + sockaddr_in in_address; |
4355 | + // init our address structure. |
4356 | + memset(&in_address,0,sizeof(in_address)); |
4357 | + //in_address.sin_len = 16; |
4358 | + in_address.sin_family = AF_INET; |
4359 | + // seperate the IP and port addresses. |
4360 | + const int IP = 0; |
4361 | + const int PORT = 1; |
4362 | + strlist addr; |
4363 | + addr = split(address,':'); |
4364 | + if (addr.size() != 2) |
4365 | + { |
4366 | + throw bad_address_exception(); |
4367 | + }; |
4368 | + if (addr[IP] != "*") |
4369 | + { |
4370 | + // first attempt name resolution |
4371 | + hostent * name = gethostbyname(addr[IP].c_str()); |
4372 | + if ((name != 0) && (name->h_length > 0)) |
4373 | + { |
4374 | + in_address.sin_addr = *( (in_addr *) (name->h_addr_list[0])); |
4375 | + } |
4376 | + else if (!inet_aton(addr[IP].c_str(),&in_address.sin_addr)) |
4377 | + { |
4378 | + throw bad_address_exception(); |
4379 | + }; |
4380 | + }; |
4381 | + if (addr[PORT] != "*") |
4382 | + { |
4383 | + // get the good port; |
4384 | + uint16_t port = lexical_cast<uint16_t>(addr[PORT]); |
4385 | + in_address.sin_port = htons(port); |
4386 | + }; |
4387 | + return in_address; |
4388 | }; |
4389 | |
4390 | string tcp_socket::sockaddr_to_str(const sockaddr_in & address) |
4391 | { |
4392 | - // get the IP address. |
4393 | - string returnme = inet_ntoa(address.sin_addr); |
4394 | - // adjust for wild card if appropriate. |
4395 | - if (returnme == "0.0.0.0") { returnme = "*"; }; |
4396 | - // get the port address |
4397 | - returnme += ":"; |
4398 | - uint16_t myport = ntohs(address.sin_port); |
4399 | - if (myport > 0 ) |
4400 | - { |
4401 | - returnme += lexical_cast<string>(myport); |
4402 | - } |
4403 | - else |
4404 | - { |
4405 | - returnme += "*"; |
4406 | - }; |
4407 | - return returnme; |
4408 | + // get the IP address. |
4409 | + string returnme = inet_ntoa(address.sin_addr); |
4410 | + // adjust for wild card if appropriate. |
4411 | + if (returnme == "0.0.0.0") { returnme = "*"; }; |
4412 | + // get the port address |
4413 | + returnme += ":"; |
4414 | + uint16_t myport = ntohs(address.sin_port); |
4415 | + if (myport > 0 ) |
4416 | + { |
4417 | + returnme += lexical_cast<string>(myport); |
4418 | + } |
4419 | + else |
4420 | + { |
4421 | + returnme += "*"; |
4422 | + }; |
4423 | + return returnme; |
4424 | }; |
4425 | |
4426 | void tcp_socket::bind(const string & address) |
4427 | { |
4428 | - if (address != "*:*") |
4429 | - { |
4430 | - sockaddr_in in_address = str_to_sockaddr(address); |
4431 | - socklen_t socklen = sizeof(in_address); |
4432 | - // try bind. |
4433 | - if (::bind(mysock, (sockaddr*) &in_address, socklen)) |
4434 | - { |
4435 | - // failed in some way. |
4436 | - _last_error = errno; |
4437 | - cant_bind_exception e; |
4438 | - e.store(address); |
4439 | - throw e; |
4440 | - }; |
4441 | - }; // nop if "*:*" is passed in. |
4442 | + if (address != "*:*") |
4443 | + { |
4444 | + sockaddr_in in_address = str_to_sockaddr(address); |
4445 | + socklen_t socklen = sizeof(in_address); |
4446 | + // try bind. |
4447 | + if (::bind(mysock, (sockaddr*) &in_address, socklen)) |
4448 | + { |
4449 | + // failed in some way. |
4450 | + _last_error = errno; |
4451 | + cant_bind_exception e; |
4452 | + e.store(address); |
4453 | + throw e; |
4454 | + }; |
4455 | + }; // nop if "*:*" is passed in. |
4456 | }; |
4457 | |
4458 | void tcp_socket::connect(const string & address, int timeout) |
4459 | { |
4460 | - sockaddr_in in_address = str_to_sockaddr(address); |
4461 | - if (::connect(mysock, ( sockaddr *) &in_address, sizeof(in_address))) |
4462 | - { |
4463 | - _last_error = errno; |
4464 | - bad_connect_exception e; |
4465 | - e.store(address); |
4466 | - throw e; |
4467 | - } |
4468 | - else |
4469 | - { |
4470 | - _status = sock_connect; |
4471 | - }; |
4472 | + sockaddr_in in_address = str_to_sockaddr(address); |
4473 | + if (::connect(mysock, ( sockaddr *) &in_address, sizeof(in_address))) |
4474 | + { |
4475 | + _last_error = errno; |
4476 | + bad_connect_exception e; |
4477 | + e.store(address); |
4478 | + throw e; |
4479 | + } |
4480 | + else |
4481 | + { |
4482 | + _status = state::sock_connect; |
4483 | + }; |
4484 | }; |
4485 | |
4486 | void tcp_socket::close() |
4487 | { |
4488 | - if (::close(mysock)) |
4489 | - { |
4490 | - _last_error = errno; |
4491 | - throw close_exception(); |
4492 | - } |
4493 | - else |
4494 | - { |
4495 | - _status = sock_close; |
4496 | - }; |
4497 | + if (::close(mysock)) |
4498 | + { |
4499 | + _last_error = errno; |
4500 | + throw close_exception(); |
4501 | + } |
4502 | + else |
4503 | + { |
4504 | + _status = state::sock_close; |
4505 | + }; |
4506 | }; |
4507 | |
4508 | int tcp_socket::put(string s, int timeout) |
4509 | { |
4510 | - // set up for the testing loop. |
4511 | - time_t endtime = time(NULL); |
4512 | - int orig_len = s.length(); |
4513 | - endtime += timeout; |
4514 | - // Try to send. |
4515 | - bool done = false; |
4516 | - while (!done) |
4517 | - { |
4518 | - // make an attempt. |
4519 | - int results = transmit(s); |
4520 | - // remove the chars already sent from the buffer and set done |
4521 | - // if appropriate. |
4522 | - if (results > 0) |
4523 | - { |
4524 | - s.erase(0,results); |
4525 | - done = (s.length() == 0) ? true : false; |
4526 | - }; |
4527 | - // decide what do do about any possible error results. |
4528 | - if (results == -1) |
4529 | - { |
4530 | - switch (errno) |
4531 | - { |
4532 | - case EBADF : |
4533 | - case ENOTSOCK: |
4534 | - { |
4535 | - done = true; |
4536 | - _last_error = errno; |
4537 | - _status = sock_close; |
4538 | - not_open_exception e; |
4539 | - e.store(s); |
4540 | - throw e; |
4541 | - break; |
4542 | - }; |
4543 | - case ENOBUFS : |
4544 | - case ENOMEM : |
4545 | - { |
4546 | - done = true; |
4547 | - _last_error = errno; |
4548 | - buffer_full_exception e; |
4549 | - e.store(s); |
4550 | - throw e; |
4551 | - break; |
4552 | - }; |
4553 | - case EINTR: |
4554 | - case EAGAIN : |
4555 | -// case EWOULDBLOCK : |
4556 | - { |
4557 | - usleep(50); |
4558 | - break; |
4559 | - }; |
4560 | - default : |
4561 | - { |
4562 | - done = true; |
4563 | - _last_error = errno; |
4564 | - general_exception e; |
4565 | - e.store(s); |
4566 | - throw e; |
4567 | - break; |
4568 | - }; |
4569 | - }; // switch (errno) |
4570 | - }; // until error, |
4571 | - if ((timeout > 0) && ((time(NULL) >= endtime))) |
4572 | - { |
4573 | - done = true; |
4574 | - }; |
4575 | - }; // continue sending until success or error or timeout. |
4576 | - // check for timeout. |
4577 | - int sent = orig_len - s.length(); |
4578 | - if (sent != orig_len) |
4579 | - { |
4580 | - timeout_exception e; |
4581 | - e.store(s); |
4582 | - throw e; |
4583 | - }; |
4584 | - return sent; |
4585 | + // set up for the testing loop. |
4586 | + time_t endtime = time(NULL); |
4587 | + int orig_len = s.length(); |
4588 | + endtime += timeout; |
4589 | + // Try to send. |
4590 | + bool done = false; |
4591 | + while (!done) |
4592 | + { |
4593 | + // make an attempt. |
4594 | + int results = transmit(s); |
4595 | + // remove the chars already sent from the buffer and set done |
4596 | + // if appropriate. |
4597 | + if (results > 0) |
4598 | + { |
4599 | + s.erase(0,results); |
4600 | + done = (s.length() == 0) ? true : false; |
4601 | + }; |
4602 | + // decide what do do about any possible error results. |
4603 | + if (results == -1) |
4604 | + { |
4605 | + switch (errno) |
4606 | + { |
4607 | + case EBADF : |
4608 | + case ENOTSOCK: |
4609 | + { |
4610 | + done = true; |
4611 | + _last_error = errno; |
4612 | + _status = state::sock_close; |
4613 | + not_open_exception e; |
4614 | + e.store(s); |
4615 | + throw e; |
4616 | + break; |
4617 | + }; |
4618 | + case ENOBUFS : |
4619 | + case ENOMEM : |
4620 | + { |
4621 | + done = true; |
4622 | + _last_error = errno; |
4623 | + buffer_full_exception e; |
4624 | + e.store(s); |
4625 | + throw e; |
4626 | + break; |
4627 | + }; |
4628 | + case EINTR: |
4629 | + case EAGAIN : |
4630 | + { |
4631 | + usleep(50); |
4632 | + break; |
4633 | + }; |
4634 | + default : |
4635 | + { |
4636 | + done = true; |
4637 | + _last_error = errno; |
4638 | + general_exception e; |
4639 | + e.store(s); |
4640 | + throw e; |
4641 | + break; |
4642 | + }; |
4643 | + }; // switch (errno) |
4644 | + }; // until error, |
4645 | + if ((timeout > 0) && ((time(NULL) >= endtime))) |
4646 | + { |
4647 | + done = true; |
4648 | + }; |
4649 | + }; // continue sending until success or error or timeout. |
4650 | + // check for timeout. |
4651 | + int sent = orig_len - s.length(); |
4652 | + if (sent != orig_len) |
4653 | + { |
4654 | + timeout_exception e; |
4655 | + e.store(s); |
4656 | + throw e; |
4657 | + }; |
4658 | + return sent; |
4659 | }; |
4660 | |
4661 | string tcp_socket::get(int maxlen, int timeout) |
4662 | { |
4663 | -/* |
4664 | -micro_timer run_time; |
4665 | -run_time.start(); |
4666 | -std::cerr << "ENTER get(" << maxlen << "," << timeout << ")" << std::endl; |
4667 | -*/ |
4668 | - string returnme = ""; |
4669 | - returnme.reserve(maxlen); |
4670 | - string in_buffer; |
4671 | - // set out timeout marker. |
4672 | - time_t endtime = time(NULL); |
4673 | - endtime += timeout; |
4674 | - timeval wait; |
4675 | - // input loop |
4676 | - bool done = false; |
4677 | - while (!done) |
4678 | - { |
4679 | - time_t waittime = endtime - time(NULL); |
4680 | - wait.tv_sec = (waittime > 0) ? waittime : 0; |
4681 | - wait.tv_usec = 10; |
4682 | - // set max timeout. |
4683 | - // the assert is used because some platforms may not properly support |
4684 | - // the SO_RCVTIMEO socket option. |
4685 | - setsockopt(mysock,SOL_SOCKET,SO_RCVTIMEO,&wait,sizeof(wait)); |
4686 | - // is there any data waiting? |
4687 | - int results = receive(in_buffer,maxlen-returnme.size()); |
4688 | - // was there an error? |
4689 | - switch (results) |
4690 | - { |
4691 | - case 0: |
4692 | - { |
4693 | - if (returnme == "") |
4694 | - { |
4695 | - throw not_open_exception(); |
4696 | - } |
4697 | - else |
4698 | - { |
4699 | - done = true; |
4700 | - } |
4701 | - break; |
4702 | - } |
4703 | - case -1 : |
4704 | - { |
4705 | - switch (errno) |
4706 | - { |
4707 | - case EBADF : |
4708 | - case ENOTCONN : |
4709 | - case ENOTSOCK : |
4710 | - { |
4711 | - done = true; |
4712 | - _last_error = errno; |
4713 | - _status = sock_close; |
4714 | - if (returnme == "") |
4715 | - { |
4716 | - not_open_exception e; |
4717 | - e.store(returnme); |
4718 | - throw e; |
4719 | - }; |
4720 | - break; |
4721 | - } |
4722 | - case EAGAIN : // shouldn't happen, but ..... |
4723 | - case EINTR : // this too.... |
4724 | - { |
4725 | - if (timeout == 0) |
4726 | - { |
4727 | - done = true; |
4728 | - }; |
4729 | - usleep(50); |
4730 | - break; |
4731 | - } |
4732 | - default : |
4733 | - { |
4734 | - done = true; |
4735 | - _last_error = errno; |
4736 | - if (returnme == "") |
4737 | - { |
4738 | - general_exception e; |
4739 | - e.store(returnme); |
4740 | - throw e; |
4741 | - }; |
4742 | - break; |
4743 | - } |
4744 | - }; // there was an error. |
4745 | - break; |
4746 | - } |
4747 | - default: |
4748 | - { |
4749 | - returnme += in_buffer; |
4750 | - break; |
4751 | - } |
4752 | - }; |
4753 | - // check boundry conditions; |
4754 | - // -- maxlen only effective if maxlen > 0. |
4755 | - if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; }; |
4756 | - // -- timeout only effective if timeout > 0. |
4757 | - if ((timeout > 0) && (time(NULL) > endtime)) { done = true; }; |
4758 | - if (timeout == 0) { done = true; }; |
4759 | -/* |
4760 | -std::cerr << "\tstatus: " << returnme.size() |
4761 | -<< ", done = " << done |
4762 | -<< " (" << run_time.interval() << ")" |
4763 | -<< std::endl; |
4764 | -*/ |
4765 | - }; // input loop. |
4766 | - // did we time out? |
4767 | - if ((timeout > 0) && (time(NULL) > endtime)) |
4768 | - { |
4769 | - timeout_exception e; |
4770 | - e.store(returnme); |
4771 | - throw e; |
4772 | - }; |
4773 | - // done! |
4774 | - return returnme; |
4775 | + string returnme = ""; |
4776 | + returnme.reserve(maxlen); |
4777 | + string in_buffer; |
4778 | + // set out timeout marker. |
4779 | + time_t endtime = time(NULL); |
4780 | + endtime += timeout; |
4781 | + timeval wait; |
4782 | + // input loop |
4783 | + bool done = false; |
4784 | + while (!done) |
4785 | + { |
4786 | + time_t waittime = endtime - time(NULL); |
4787 | + wait.tv_sec = (waittime > 0) ? waittime : 0; |
4788 | + wait.tv_usec = 10; |
4789 | + // set max timeout. |
4790 | + // the assert is used because some platforms may not properly support |
4791 | + // the SO_RCVTIMEO socket option. |
4792 | + setsockopt(mysock,SOL_SOCKET,SO_RCVTIMEO,&wait,sizeof(wait)); |
4793 | + // is there any data waiting? |
4794 | + int results = receive(in_buffer,maxlen-returnme.size()); |
4795 | + // was there an error? |
4796 | + switch (results) |
4797 | + { |
4798 | + case 0: |
4799 | + { |
4800 | + if (returnme == "") |
4801 | + { |
4802 | + throw not_open_exception(); |
4803 | + } |
4804 | + else |
4805 | + { |
4806 | + done = true; |
4807 | + } |
4808 | + break; |
4809 | + } |
4810 | + case -1 : |
4811 | + { |
4812 | + switch (errno) |
4813 | + { |
4814 | + case EBADF : |
4815 | + case ENOTCONN : |
4816 | + case ENOTSOCK : |
4817 | + { |
4818 | + done = true; |
4819 | + _last_error = errno; |
4820 | + _status = state::sock_close; |
4821 | + if (returnme == "") |
4822 | + { |
4823 | + not_open_exception e; |
4824 | + e.store(returnme); |
4825 | + throw e; |
4826 | + }; |
4827 | + break; |
4828 | + } |
4829 | + case EAGAIN : // shouldn't happen, but ..... |
4830 | + case EINTR : // this too.... |
4831 | + { |
4832 | + if (timeout == 0) |
4833 | + { |
4834 | + done = true; |
4835 | + }; |
4836 | + usleep(50); |
4837 | + break; |
4838 | + } |
4839 | + default : |
4840 | + { |
4841 | + done = true; |
4842 | + _last_error = errno; |
4843 | + if (returnme == "") |
4844 | + { |
4845 | + general_exception e; |
4846 | + e.store(returnme); |
4847 | + throw e; |
4848 | + }; |
4849 | + break; |
4850 | + } |
4851 | + }; // there was an error. |
4852 | + break; |
4853 | + } |
4854 | + default: |
4855 | + { |
4856 | + returnme += in_buffer; |
4857 | + break; |
4858 | + } |
4859 | + }; |
4860 | + // check boundry conditions; |
4861 | + // -- maxlen only effective if maxlen > 0. |
4862 | + if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; }; |
4863 | + // -- timeout only effective if timeout > 0. |
4864 | + if ((timeout > 0) && (time(NULL) > endtime)) { done = true; }; |
4865 | + if (timeout == 0) { done = true; }; |
4866 | + }; // input loop. |
4867 | + // did we time out? |
4868 | + if ((timeout > 0) && (time(NULL) > endtime)) |
4869 | + { |
4870 | + timeout_exception e; |
4871 | + e.store(returnme); |
4872 | + throw e; |
4873 | + }; |
4874 | + // done! |
4875 | + return returnme; |
4876 | }; |
4877 | |
4878 | - |
4879 | string tcp_socket::getln(string eol, int maxlen, int timeout) |
4880 | { |
4881 | - // args check. |
4882 | - if (eol == "") |
4883 | - { |
4884 | - throw bad_args_exception(); |
4885 | - return eol; |
4886 | - }; |
4887 | - // setup. |
4888 | - string returnme = ""; |
4889 | - returnme.reserve(maxlen); |
4890 | - int targetlen = eol.length(); |
4891 | - int searchlen = targetlen - 1; |
4892 | - time_t endtime = time(NULL); |
4893 | - endtime += timeout; |
4894 | - bool done = false; |
4895 | - bool success = false; |
4896 | - // first, get at least as many characters as are in the eol string. |
4897 | - try |
4898 | - { |
4899 | - int wait_time = timeout; |
4900 | - if (timeout < 0) { wait_time = 0; }; |
4901 | - returnme = get(targetlen,wait_time); |
4902 | - } |
4903 | - catch (timeout_exception e) |
4904 | - { |
4905 | - // if get timed out we may be done. |
4906 | - if (timeout >= 0) { done = true; }; |
4907 | - returnme = e.comment(); |
4908 | - }; |
4909 | - // We only need to continue if we have not gotten our token yet. |
4910 | - if ((!done) && (returnme.length() >= targetlen)) |
4911 | - { |
4912 | -// success = returnme.substr(returnme.length()-targetlen,targetlen) == eol; |
4913 | - success = returnme.find(eol,returnme.length()-targetlen) != string::npos; |
4914 | - }; |
4915 | - while (!done && !success) |
4916 | - { |
4917 | - // still more to get, if we have time. |
4918 | - int timeleft = endtime - time(NULL); |
4919 | - timeleft = (timeleft > 0) ? timeleft : 0; |
4920 | - // can we increase our get length? |
4921 | - int getlen = 1; |
4922 | - if (searchlen > 1) |
4923 | - { |
4924 | - // see if a token start is near. |
4925 | - if (returnme.find(eol[0],returnme.length()-searchlen) == string::npos) |
4926 | - { |
4927 | - // great!.. get just less than one token's worth. |
4928 | - getlen = searchlen; |
4929 | - } |
4930 | - }; |
4931 | - // okay.. let's get the next chunk |
4932 | - try |
4933 | - { |
4934 | - returnme += get(getlen,timeleft); |
4935 | - } |
4936 | - catch (timeout_exception e) |
4937 | - { |
4938 | - if (timeout >= 0) { done = true; }; |
4939 | - }; |
4940 | - // check boundary conditions. |
4941 | - // -- did we get it? |
4942 | - if (returnme.length() >= targetlen) |
4943 | - { |
4944 | -// success = returnme.substr(returnme.length()-targetlen,targetlen) == eol; |
4945 | - success = returnme.find(eol,returnme.length()-targetlen) != string::npos; |
4946 | - }; |
4947 | - // -- maxlen only effective if maxlen > 0. |
4948 | - if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; }; |
4949 | - }; |
4950 | - // did we error out? |
4951 | - if (!success) |
4952 | - { |
4953 | - // what type of error was it? |
4954 | - if ((maxlen > 0) && (returnme.length() >= maxlen)) |
4955 | - { |
4956 | - overrun_exception e; |
4957 | - e.store(returnme); |
4958 | - throw e; |
4959 | - } |
4960 | - else |
4961 | - { |
4962 | - timeout_exception e; |
4963 | - e.store(returnme); |
4964 | - throw e; |
4965 | - }; |
4966 | - }; |
4967 | - return returnme; |
4968 | + // args check. |
4969 | + if (eol == "") |
4970 | + { |
4971 | + throw bad_args_exception(); |
4972 | + return eol; |
4973 | + }; |
4974 | + // setup. |
4975 | + string returnme = ""; |
4976 | + returnme.reserve(maxlen); |
4977 | + int targetlen = eol.length(); |
4978 | + int searchlen = targetlen - 1; |
4979 | + time_t endtime = time(NULL); |
4980 | + endtime += timeout; |
4981 | + bool done = false; |
4982 | + bool success = false; |
4983 | + // first, get at least as many characters as are in the eol string. |
4984 | + try |
4985 | + { |
4986 | + int wait_time = timeout; |
4987 | + if (timeout < 0) { wait_time = 0; }; |
4988 | + returnme = get(targetlen,wait_time); |
4989 | + } |
4990 | + catch (timeout_exception e) |
4991 | + { |
4992 | + // if get timed out we may be done. |
4993 | + if (timeout >= 0) { done = true; }; |
4994 | + returnme = e.comment(); |
4995 | + }; |
4996 | + // We only need to continue if we have not gotten our token yet. |
4997 | + if ((!done) && (returnme.length() >= targetlen)) |
4998 | + { |
4999 | + success = returnme.find(eol,returnme.length()-targetlen) != string::npos; |
5000 | + }; |
Per earlier discussion and after extensive unit testing and no objections, this merge is approved.