-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patholagarro.txt
251 lines (242 loc) · 11.6 KB
/
olagarro.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/// @file
/// @mainpage Documentation
/// Olagarro is a C++ utility library which aims to provide small, easily usable, portable and useful utilities. Currently it only contains the concurrency module.
///
/// License is zlib/libpng (http://opensource.org/licenses/zlib-license.php)
///
/// @section concurrency_sec Concurrency module
/// Concurrency module provides some facilities to take advantage of multiple CPUs of modern machines in a very easy and straightforward way. It uses
/// futures paradigm in order to launch concurrent jobs or tasks in an unobstructive way. It is inspired by <a href="http://qt-project.org/doc/qt-5/qtconcurrent-index.html">Qt's concurrency module</a>.
///
/// It's written in C++ 2003 and does not use C++11 features in order to be able to offer its functionality in older compilers. Also in C++11 there is std::async so concurrency module would be redundant. In some
/// way it can be seen as a C++ 2003 version of C++11's std::async.
///
/// @subsection Portability
/// Concurrency module uses <a href="http://tinythreadpp.bitsnbites.eu/">TinyThread++</a> in order to have portable threads, so module is as portable as that library. It have been tested on Windows, Linux, Mac OS X and iOS.
///
///
/// @subsection Installation
/// Module's installation is very easy: just unzip library somewhere in your project's tree and add .h and .cpp files to it in your IDE or project file.
/// There is no need to build a library, configure it or something similar.
///
/// @subsection Examples
/// Concurrency module is very easy to use. Here are some examples and it does not get more complicated. First we see how to launch a task in another thread:
///
/// @code
///
///
/// #include "olagarro/concurrency.h"
///
/// using namespace Olagarro;
///
/// float calculateSomeValue(const std::vector<float>& someData)
/// {
/// float valueResult = 0.0f;
/// // ...
/// return valueResult;
/// }
///
/// void otherFunction()
/// {
/// std:vector<float> data(getSomeData());
///
/// Concurrency::Result<float> someValue = Concurrency::launchJob(calculateSomeValue, data);
///
/// std::cout << "Result is = " << someValue.result() << std::endl;
/// }
///
/// @endcode
///
/// In this example calculateSomeValue() runs in a different thread than calling code. Calling someValue.result() we block calling thread until calculateSomeValue()
/// finishes its job or it just returns calculated value immediately if job has been done. This way using concurrency module we can launch
/// jobs, do some other task while they are running in another threads and then ask for their result, blocking if its needed. No thread manual handling is required at all.
///
/// It is possible to launch any number of jobs: concurrency module will enqueue and process them as soon as it can, which is when a physical CPU core is free from a previous Job.
///
/// Other utility provided by concurrency module is concurrentFor, which spawns as many threads as machine's CPU core number:
///
/// @code
///
/// #include "olagarro/concurrency.h"
///
/// using namespace Olagarro;
///
/// void addOK(int index, std::string& str)
/// {
/// str += " OK";
/// }
///
/// void otherFunction()
/// {
/// std::vector<std::string> messages(getMessages());
///
/// Future<void> messagesFuture = Concurrency::concurrentFor(messages.begin(), messages.end(), addOK);
///
/// messagesFuture.result(); // Block until all processing is done
///
/// std::cout << "All strings processed\n";
/// }
///
/// @endcode
///
/// In this example we process a vector of strings. For each string a call is made to addOk() function, passing element's index and element itself to it.
/// If that code runs in a machine with 4 CPUs, messages vector will be split in 4 parts and each part will be processed in its own thread. concurrentFor() call is no blocking,
/// so we need a Future in order to know when it has finished its job.
///
/// These two examples summarize what concurrency module can do. There are other versions which take methods or functors instead of functions but everything falls in one of these two categories.
///
/// @subsection raceconds Race conditions
///
/// If we are using for example a std::vector<int> in a function which modifies it and we call it with launchJob or concurrentFor, this std::vector<int> variable will be modified in another one or more threads. The calling
/// thread should not modify it at the same time because concurrency module takes no care avoiding data races. That is, no locking or synchronization job is done so use this module with totally independent tasks. In the case
/// of concurrentFor the std::vector<int> would be split in several chunks. Function assumes each element of the vector can be processed on its own, without the intervention of the other elements of the vector.
///
/// @subsection Performance
/// This concurrency module nor any other concurrency library will offer a "magical" performance boost to your code. Sometimes serial code will be faster (even by several orders of magnitude) than
/// concurrent one due to the type of calculations, memory access, etc you are doing. Concurrency only makes sense when you have heavy tasks which take much more time doing its job than managing its launching, or
/// to avoid blocking some important thread (like GUI thread in a typical desktop application). Fortunately concurrency module is very unobstructive so you can easily make your code take
/// advantage of its facilities, profile your new code and see if it's worth or not to go concurrent.
///
///
/// @subsection Implementation Implementation details
/// Concurrency module manages a thread pool under the hood. This pool contains several threads blocked, waiting for new tasks. When launchJob() or concurrentFor()
/// is called, those functions create tasks and enqueue them in the task queue. This way tasks are executed in sequential order (first in first executed) but
/// due to their asynchronous nature they finish in a non-ordered fashion.
/// Be careful: concurrency module is not designed to have nested tasks. In other words, it's dangerous that a function launched by launchJob() makes a call to launchJob(), thread pool could get blocked forever.
///
///
/// @section bytestream_sec ByteStream
/// This class provides an easy way to deal extracting and adding different data types from and to a raw byte buffer. Thanks to operator overloading it is very simple to
/// define insertion and extraction means for custom data types.
/// @subsection Portability
/// ByteStream class uses only standard C++ so it is portable to a very large number of systems.
///
/// @subsection Installation
/// Class is contained in a .h and a .cpp files. Just copy them in your project and start using the class. There is no need to build a library, configure it or something similar.
///
/// @subsection Examples
/// ByteStream is just a bytes buffer which works like C++ standard streams. When we create one it is empty
///
/// @code
/// #include <bytestream.h>
/// #include <cassert.h>
///
/// Olagarro::ByteStream data;
///
/// assert(data.size() == 0);
///
/// @endcode
///
/// We can add any POD to it with << operator
///
/// @code
/// int a = 10;
///
/// data << a;
/// @endcode
///
/// Now "data" is a buffer big enough to hold an int and it contains a copy of "a" variable's bytes
///
/// It is possible to store raw arrays as any other POD:
///
/// @code
/// const double b[100] = {...};
///
/// data << b;
/// @endcode
///
/// Now we have an int and then 100 doubles in "data" ByteStream object. We can retrieve this data with >> operator:
///
/// @code
/// int intValue;
/// double doubleValues[100];
///
/// data >> intValue >> doubleValues;
/// @endcode
///
/// Everything shown so far works also with structs and classes which contain PODs. If we need to deal with more elaborated data types we need to provide our own custom << and >> operators.
/// See ByteStream test file to see one possible implementation of these operators for std::string and std::vector classes
///
/// Finally ByteStream provides a convenience functions to deal with files: loadFromFile() and saveToFile():
///
/// @code
///
/// Olagarro::ByteStream data;
///
/// data << ...
///
/// Olagarro::ByteStream::saveToFile(data, "somedata.bin");
///
/// ...
///
/// Olagarro::ByteStream fileData;
///
/// Olagarro::ByteStream::loadFromFile(fileData, "somedata.bin");
///
/// fileData >> ...
///
/// @endcode
///
/// Take a look to documentation to see more all the member functions of ByteStream class.
///
///
///
/// @section signalslot_sec Signal/slot system
/// This collection of classes implement a very small signal/slot system in C++2003
///
/// @subsection Portability
/// Signal/slot class uses only standard C++ so it is portable to a very large number of systems.
///
/// @subsection Installation
/// Just add signalslot.h to the file you need it
///
/// @subsection Examples
/// Signal/slot system is an implementation of the observer pattern. Signal is the observable object and slot is the observer part. The following example illustrates it:
///
/// @code
/// // We have the following function
/// void onDoorClosed(int doorId)
/// {
/// std::cout << "Door " << doorId << " has been closed\n";
/// }
///
/// // This signal will be fired when a door is closed
/// Signal1<int> doorClosedSignal;
///
/// // Slot links a signal with the receiving end, in this case a free function
/// Slot1<int> onDoorClosedSlot(onDoorClosed, doorClosedSignal); // Notice how we pass the function (mandatory) and signal (optional)
///
/// // We can connect signal later, instead of using it in the constructor:
/// onDoorClosedSlot.connect(doorClosedSignal);
/// // Somewhere in the code
/// ...
/// doorClosedSignal.fire(25); // --> Makes to print "Door 25 has been closed"
///
/// // We can disconnect slot from signal
/// doorClosedSlot.disconnect(doorClosedSignal);
/// // We can disconnect a slot from all of its signals
/// doorClosedSlot.disconnectAll();
/// // Also we can disconnect all slots connected to a signal
/// doorClosedSignal.disconnectAll();
/// @endcode
///
/// Slots can work with free functions, object/method pairs and with functors. A slot can be connected to an arbitrary number of signals and a signal can also be connect to an arbitrary number of slots. When
/// a slot is destroyed it disconnects itself from all of its connected signals and the opposite is true to, so there is no need to manage manually slot/signal disconnections.
/// Due to C++2003' limitations (no variadic templates) current implementation only supports from 0 to 5 arguments calls (hence the signal0, signal1, etc names). Also there is no way to recover calls' return values,
/// system assumes everything returns void. Take into account signal/slot is just like a normal function call, so no threading issue is contemplated at all, system's client is responsible of dealing with synchronization etc.
/// Look at the test's main.cpp file for more examples.
Copyright (c) 2014 Inaki Griego
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.